业务中需要处理Csv文件,但是在网上兜兜转转没有找到合适的文件,再加上自己对Csv文件了解确实不是很深入,所以感觉特别麻烦。
于是想到尝试自己写一篇以备后面使用,附带详细的文字备注
我们需要引入pom文件
javacsv目前已不再更新,最高版本好像是2.1,我这里使用的是2.0版本
<!--开源的javacsv 不再更新-->
<dependency>
<groupId>net.sourceforge.javacsv</groupId>
<artifactId>javacsv</artifactId>
<version>2.0</version>
</dependency>
这里的话就不说废话了,直接上代码,代码里有详细注释
package org.jeecg.modules.demo3.common;
import com.amazonaws.services.s3.model.S3ObjectInputStream;
import com.csvreader.CsvWriter;
import org.apache.commons.fileupload.FileItem;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
/**
* @author 任硕
* @create 2021-03-23 10:10
*/
public class CsvFileUtil {
/**写cCSV文件*/
public static <T> void writeCSV(Collection<T> dataset, String csvFilePath, String[] csvHeaders) {
try {
/** 定义路径,分隔符,编码**/
CsvWriter csvWriter = new CsvWriter(csvFilePath, ',', Charset.forName("GBK"));
/** 写表头 */
csvWriter.writeRecord(csvHeaders);
/**遍历集合写内容*/
Iterator<T> it = dataset.iterator();
/**
* csv写入文件的方式有些特殊,每一行文件使用一个 String[] 数组进行写入
* 这里通过迭代器获取集合中的数据,放入到类反射生成的String[]中逐行写入
* **/
while (it.hasNext()) {
T t = (T) it.next();
/**获取类属性*/
Field[] fields = t.getClass().getDeclaredFields();
String[] csvContent=new String[fields.length];
for (short i = 0; i < fields.length; i++) {
Field field = fields[i];
String fieldName = field.getName();
String getMethodName = "get"
+ fieldName.substring(0, 1).toUpperCase()
+ fieldName.substring(1);
try {
Class tCls = t.getClass();
Method getMethod = tCls.getMethod(getMethodName,new Class[] {});
Object value = getMethod.invoke(t, new Object[] {});
if (value == null) {
continue;
}
/**取值并赋给数组*/
String textValue=value.toString();
csvContent[i]=textValue;
}catch (Exception e) {
e.getStackTrace();
}
}
/**写入数据*/
csvWriter.writeRecord(csvContent);
}
csvWriter.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**读csv文件*/
public static List<String[]> readerCSV(InputStream inputStream) {
BufferedReader reader= null;
/**读取CSV文件流返回list集合*/
List<String[]> strList=new ArrayList<>();
try {
/**设置读取时候采用的编码格式,因为文件写入的时候也是用的GBK所以这里依然采用GBK*/
InputStreamReader inputStreamReader = new InputStreamReader(inputStream,"GBK");
/**BufferedReader里面就是我们拿到的所有的文件流了*/
reader = new BufferedReader(inputStreamReader);
/**定义行,每次读取一行内容*/
String line;
while ((line = reader.readLine()) != null) {
/**拆分line,获取里面的全部内容,设置为-1可以防止丢失数据*/
/**(里面的)正则是为了防止解析的String数组有空行会多出来列的情况*/
String[] rows=line.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)",-1);
strList.add(rows);
}
reader.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return strList;
}
}
writeCSV方法里面的三个参数依次为 数据集合、文件保存的本地路径、文件表头信息,可以看到是先在本地生成一个含有表头的Csv文件,然后再根据java的反射获取实体类属性生成一个用来保存表格一行数据的数组,最后执行写入操作。
readerCSV方法里面的参数就是当前的文件流了,因为在执行writeCSV的时候我们发现使用数组进行写入的,所以相对的,我们读取时也是尽量用数组来进行接收数据
备注:注意编码格式,乱码的话很烦。