使用方法:

  1. 提供把实例数据输出到磁盘csv文件的功能
  2. 提供读取csv文件,并封装成指定实例的功能
  3. 小工具自己依赖了slf4j+logbak,以及fastJson,如果与系统冲突,可以在pom文件中去除
  4. 可以自己手动封装jar包,引入到自己的工程,也可以复制CsvUtils.java和CsvConfig.java到工程,直接使用

踩的坑:

反射:

使用反射,创建新实例并给各个属性赋值,获取属性值后,调用set方法赋值,因为获取的值都是String类型,需要根据属性值类型对值转型。

  • 一开始希望写一个转类型方法,根据传入的Field的类型,把String类型的值转成属性值,构造的方法类似:
private <T> T tranform(Field field, String value){switch(field.getType().getSimpleName()){case "String":...return (T)xxx;case ...}
}

但是出现一个问题,没法转换,一直提示无法把String转换成Object.后来放弃了

  • 打算使用反射的方式,使用基础类型的封装类型中的valueOf方法,思路大致是:
  1. a. 获取Field的类型全称
  2. b. 根据全称,使用Class.forName()获取对应的Class实例
  3. c. 根据反射,获取valueOf方法
  4. d. 执行valueOf方法,把String类型的值转成Field的Type

代码大致是,手打的,不是真正的代码:

String typeName = field.getType.getName();
Class<?> typeClass = Class.forName(typeName);
Method valueOf = typeClass.getDeclearMethod("valueOf",java.lang.String);
Object obj = typeClass.newInstence(); //这一步出错
valueof.invoke(obj,value);  //把要赋予属性的值,由String类型转换成属性类型

但是在获取封装类型的实例是,也就是 Object obj = typeClass.newInstence(); 这一步,提示,无法获取Integer类型的实例,提示是的没有`<init>`什么的,抛出异常的位置是 C:/Program Files/Java/jdk1.8.0_101/src.zip!/java/lang/Class.java:3082 。后来琢磨了一会,发现只有String类型有无参构造方法,其他封装类型都没有无参构造方法,不知道是不是这个原因,String类型可以通过反射获取实例,其他封装类型不能获取实例。

最后放弃挣扎,使用枚举,使用封装类型的valueOf方法对值进行转换。实现方式后面代码。

1、工具实现代码

package com.donfaquir.csv;import com.csvreader.CsvReader;
import com.csvreader.CsvWriter;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;/*** @author: * @description: 提供csv文件的操作方法* @date Create in 2018/12/24 15:01* @modified By:*/
public class CsvUtil {private  final Logger log = LoggerFactory.getLogger(CsvUtil.class);/*** 读取csc文件** @param filePath      文件路径* @param clazz         指定类型* @param csvConfig     配置信息* @return              读取结果*/public  <T> List<T> readFile(String filePath, Class<T> clazz, CsvConfig csvConfig) throws Exception {if (null == filePath || null == clazz) {return null;}List<T> result = new ArrayList<>(10);this.checkCsvConfig(csvConfig);CsvReader reader = new CsvReader(filePath, csvConfig.getSeparator(), Charset.forName(csvConfig.getCharset()));//获取类方法Map<Field, Method> methods = new HashMap<>(11);Field[] fields = clazz.getDeclaredFields();if (fields == null) {log.error("========未获取到类{}的属性值,请确认类{}是否传入正确========", clazz.getName(), clazz.getName());return null;}for (int i = 0; i < fields.length; i++) {String methodName = "set" + fields[i].getName().substring(0, 1).toUpperCase() + fields[i].getName().substring(1);Method method = clazz.getMethod(methodName, fields[i].getType());if (method == null) {log.info("====类{}中没有属性{}的set方法,请确定是否实现====", clazz.getName(), fields[i].getName());continue;}methods.put(fields[i], method);}//跳过头文件reader.readHeaders();String[] headers = reader.getHeaders();if(null == headers || headers.length <=0){log.error("========文件< {} >缺少数据头,请增加数据头到文件========",filePath);return null;}while (reader.readRecord()) {T obj = (T)clazz.newInstance();Set<Field> keys = methods.keySet();for (Field key : keys) {key.setAccessible(true);String value = reader.get(key.getName());if(StringUtils.isBlank(value)){continue;}switch (key.getType().getSimpleName()) {case "Integer":methods.get(key).invoke(obj,Integer.valueOf(value));break;case "String":methods.get(key).invoke(obj,value);break;case "Boolean":methods.get(key).invoke(obj,Boolean.valueOf(value));break;case "Long":methods.get(key).invoke(obj,Long.valueOf(value));break;case "Float":methods.get(key).invoke(obj,Float.valueOf(value));break;case "Double":methods.get(key).invoke(obj,Double.valueOf(value));break;case "Date":try {methods.get(key).invoke(obj,new SimpleDateFormat(csvConfig.getDateFormat()).parse(value));break;} catch (ParseException e) {log.info("====日期转换失败,使用的日期格式为:{},与给定的日期数据格式不匹配,请重新指定日期转换格式====",csvConfig.getDateFormat());log.info("====错误原因:{}",e);throw new RuntimeException(e);}default:methods.get(key).invoke(obj,value);break;}}result.add(obj);}reader.close();return result;}/*** 读取csc文件* 默认编码格式是本地编码格式* @param filePath      文件路径* @param separator     分隔符* @param t             指定类型* @return              读取结果*/public  <T> List<T> readFile(String filePath, char separator, Class<T> t) throws Exception {return this.readFile(filePath,t,this.initCsvConfig());}/*** 把缓存内容写入到csv文件** @param filePath       文件路径* @param cacheContainer 缓存容器* @param csvConfig      配置信息* @return 写入是否成功*/public <T> boolean writeFile(String filePath, List<T> cacheContainer, Class<T> t,CsvConfig csvConfig) {CsvWriter writer;if (StringUtils.isBlank(filePath) || CollectionUtils.isEmpty(cacheContainer) || null == t) {return false;}this.checkCsvConfig(csvConfig);writer = new CsvWriter(filePath, csvConfig.getSeparator(), Charset.forName(csvConfig.getCharset()));//获取实体类中的属性Field[] fields = t.getDeclaredFields();//生成数据头String[] headers = new String[fields.length];for (int i = 0; i < fields.length; i++) {headers[i] = fields[i].getName();}//写入到文件try {writer.writeRecord(headers);for (T obj : cacheContainer) {String[] str = coverFieldsValue(obj,csvConfig);writer.writeRecord(str);}} catch (Exception e) {e.printStackTrace();}writer.close();return true;}/*** 把缓存内容写入到csv文件* 默认编码格式是本地编码格式* @param filePath       文件路径* @param cacheContainer 缓存容器* @return 写入是否成功*/public <T> boolean writeFile(String filePath, List<T> cacheContainer, Class<T> t) {return this.writeFile(filePath,cacheContainer,t,this.initCsvConfig());}/*** 把传入的实例属性的值封装成字符串数组** @param obj       实例* @return          字符串数组* @throws Exception    异常*/private <T>  String[] coverFieldsValue(T obj,CsvConfig csvConfig) throws Exception {String[] result ;Class<?> clazz = obj.getClass();Field[] fields = clazz.getDeclaredFields();if (null == fields || fields.length <= 0) {return null;}result = new String[fields.length];for (int i = 0; i < fields.length; i++) {new Date();String methodName = "get" + fields[i].getName().substring(0, 1).toUpperCase() + fields[i].getName().substring(1);Method method = clazz.getMethod(methodName);Object value = method.invoke(obj);if(null == value){continue;}if("Date".equals(fields[i].getType().getSimpleName())){Date date = (Date)value;result[i] = new SimpleDateFormat(csvConfig.getDateFormat()).format(date);continue;}result[i] = value.toString();}return result;}/*** 构造一个默认的配置实例* 默认编码格式为本地系统编码格式* @return      设有默认值的配置实例*/private CsvConfig initCsvConfig(){String charset = System.getProperty("file.encoding");return new CsvConfig(charset,"yyyy-MM-dd HH:mm:ss:SSS",',');}/*** 检测给予系统配置信息的完整性* @param csvConfig        给定的配置实例*/private void checkCsvConfig(CsvConfig csvConfig){if(null == csvConfig){csvConfig = initCsvConfig();}else{if(null == csvConfig.getCharset()){csvConfig.setCharset(System.getProperty("file.encoding"));}if(null == csvConfig.getDateFormat()){csvConfig.setDateFormat("yyyy-MM-dd HH:mm:ss:SSS");}//没有指定分隔符if(0 == csvConfig.getSeparator()){csvConfig.setSeparator(',');}}}
}

  

2、参数实体类

用于指定编码类型、日期格式和分隔符

package com.donfaquir.csv;/*** @author: * @description:    工具配置类* @date Create in 2018/12/26 10:09* @modified By:*/
public class CsvConfig {/** 字符编码 */private String charset;/** 日期格式 */private String dateFormat;/** 分隔符 */private char separator;public CsvConfig(){}public CsvConfig(String charset, String dateFormat, char separator){this.charset = charset;this.dateFormat = dateFormat;this.separator = separator;}public String getCharset() {return charset;}public void setCharset(String charset) {this.charset = charset;}public String getDateFormat() {return dateFormat;}public void setDateFormat(String dateFormat) {this.dateFormat = dateFormat;}public char getSeparator() {return separator;}public void setSeparator(char separator) {this.separator = separator;}
}

  

3、使用demo

import bean.User;
import com.donfaquir.csv.CsvConfig;
import com.donfaquir.csv.CsvUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.util.List;/*** @author: * @description:    测试类* @date Create in 2018/12/24 15:22* @modified By:*/
public class Demo {private  static Logger log = LoggerFactory.getLogger(Demo.class);public static void main(String[] args){String filePath = System.getProperty("user.home")+"/csv_test.csv";CsvConfig csvConfig = new CsvConfig("gbk","yyyy-MM-dd HH:mm:ss:SSS",',');CsvUtil csvUtil = new CsvUtil();//写文件代码/* User user = new User("李磊", "男", 14, new Date(), true, 133443L);User user1 = new User("jack", "M", 22, new Date(), false, 134L);ArrayList<User> users = new ArrayList<>(3);users.add(user);users.add(user1);csvUtil.writeFile(filePath, users, User.class,csvConfig);*///读文件代码try {List<User> objects = csvUtil.readFile(filePath, User.class,csvConfig);if(CollectionUtils.isEmpty(objects)){log.info("====没有从文件{}获取到值====",filePath);}log.debug("==获取的结果总数:{}",objects.size());
//            log.debug("==获取的结果:{}", JSON.toJSONString(objects));} catch (Exception e) {e.printStackTrace();}}
}

  

4、使用中用到的domain类

package bean;import java.util.Date;/*** @author: * @description:    用户类* @date Create in 2018/12/24 15:21* @modified By:*/
public class User {/** 用户名 */private String name;/** 性别 */private String sex;/** 年龄 */private Integer age;/** 生日 */private Date birthday;/** 信息是否公开 */private Boolean visible;/** 过车整形id */private Long longId;public User() {super();}public User(String name, String sex, Integer age, Date birthday, Boolean visible, Long longId) {this.name = name;this.sex = sex;this.age = age;this.birthday = birthday;this.visible = visible;this.longId = longId;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}public Boolean getVisible() {return visible;}public void setVisible(Boolean visible) {this.visible = visible;}public Long getLongId() {return longId;}public void setLongId(Long longId) {this.longId = longId;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}
}

  

转载于:https://www.cnblogs.com/donfaquir/p/10179353.html

CsvReader和CsvWriter操作csv文件相关推荐

  1. java csvreader使用_java使用CsvReader和CsvWriter对csv文件内容进行读取和写入操作

    package IO; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import ...

  2. 使用CsvReader读取和写入csv文件

    使用CsvReader读取和写入csv文件的简单操作Demo: import com.csvreader.CsvReader; import com.csvreader.CsvWriter;impor ...

  3. python中csv文件操作_python中操作csv文件

    python中操作csv文件 读取csv improt csv f = csv.reader(open("文件路径","r")) for i in f: pri ...

  4. Pandas 操作 csv 文件

    Pandas 操作 csv 文件 官方英文文档 官方文档PDF下载 中文文档 一.安装 Pandas 安装 Pandas: pip3 install pandas 导入 Pandas: import ...

  5. opencsv操作CSV文件

    1. CSV文件简介 现在好多的网站中导出的文件会出现一种csv文件,我们接下来学习一下csv文件的导出方式. CSV文件:Comma-Separated Values,中文叫逗号分隔值或者字符分割值 ...

  6. 使用.NET类库操作CSV文件

    CSV文件,是指使用逗号对数据进行分割的文本数据文件.昨天有人提出了一个问题,就是怎么对CSV文件进行操作,并且给出了一个类的定义.我根据这个类定义实现了一个能够读些CSV文件的类. 由于涉及到了字符 ...

  7. pythoncsv文件的操作_python操作CSV文件

    概念:CSV是逗号分隔值或者字符分割值,其文件以纯文本形式存储表格数据.CSV文件可以用文本文件或者转换成EXCEL(直接用EXCEL也可以,但是可能会有一些问题)打开.因此更适合通过CSV文件进行程 ...

  8. java解析csv文件工具类,java操作CSV文件工具类

    离线路灯 UID:3 注册时间2011-08-21 最后登录2021-03-15 在线时间5398小时 发帖659 精华44 金币3650 威望1881 股份280 发帖659 金币3650威望188 ...

  9. Csvmapper操作csv文件

    csv文件上传/读取/压缩/保存 import com.fasterxml.jackson.dataformat.csv.CsvMapper; import com.fasterxml.jackson ...

最新文章

  1. GIT_忽略文件和属性文件配置
  2. 【转】如何在github上fork一个项目来贡献代码以及同步原作者的修改 -- 不错
  3. 人类在计算机设计方面已经进入了一个误区
  4. python子进程关闭fd_如果创建了multiprocessing.Pool,Python子进程wait()将失败
  5. SpringBoot项目遇到的一些问题
  6. xtrabackup对MySQL数据库的备份及恢复教程
  7. linux那些事之early pape fault
  8. 中科院发布“木兰”处理意见;互联网公司合力应对新型肺炎;PHP 7.4.2 发布| 极客头条...
  9. 二进制文件(.bin)查看
  10. python修改xml文件内容,不废话,拿来即用
  11. 数学画图软件_数学建模竞赛要点分析 amp; 实用工具网站收集
  12. 四川大学计算机专业调剂,四川大学计算机学院(软件学院)2019考研调剂信息...
  13. android socket代理app,android socket客户端app
  14. 装配图中齿轮的画法_机械制图教程(8.2)装配图的规定画法和特殊画法
  15. 【评测】MP DSS肠炎模型专用
  16. Chrome浏览器安装Vue.js devtools插件
  17. 3dmax入门教程(一)
  18. 前端大屏模板分享-可在线浏览
  19. Goat Rodeo:面向Web应用的统一数据模型
  20. Scratch案例——巧解数学题,求累加和

热门文章

  1. 今天!微信新动作!猝不及防520红包又来了!!
  2. 写一段python判断是否是闰年的代码
  3. matlab导出无损图像,matlab保存图片的方法
  4. 深挖价值,让数据“说话”,你准备好了吗?
  5. 图像笔记(一)——目标检测
  6. JavaScript百炼成仙阅读笔记
  7. 计算机保研er 8月应该做什么?
  8. 请用c++写一个视频为转换成GIF的代码
  9. EtherCAT运动控制卡开发教程之Qt(中):小线段连续轨迹加工、暂停与继续
  10. webpack 多页面 html,基于webpack实现多html页面开发框架八 html引入图片打包和公共页面模块复用...