CSV(Comma-Separated Values)是一种常见的文件格式,用于存储和传输表格数据。它是一种纯文本文件,其中的数据以逗号作为分隔符进行分隔。每行表示一条数据记录,每个字段(列)之间使用逗号进行分隔。
工作中我们可能会遇到某些场景需要对某个文件的内容进行繁琐而又没有技术性的操作,由此我们可以设法使用我们的程序将文件中内容读取出来并做我们想要的处理。
下面我举其中一个例子:
如何将csv文件中的内容读取出来并转换成对象,方便我们对其进行处理?
比如我们有如下csv文件:
id1,id2
1,2
6,9
3,8
10,54
写一个DTO类来放我们csv文件中的内容
/**
* 属性值不要用基本数据类型哦
* 如果想用基本数据类型 可以在代码中动动自己的小脑子,我这里就不在赘述了
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class ExcelObj {
private String id1;
private String id2;
}
写一个工具类来读取CSV文件并且将其中的内容转换为对象
package ReadCSV.util;
import org.apache.commons.lang3.StringUtils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class HPoiUtils {
public static List exeCsv(File file, List<String> listField,Class c){
return exeCsv(file,listField,c,true);
}
public static List exeCsv(File file, List<String> listField,Class c,boolean hasHeader){
//得到字符串数据
List<String> resultStrList = readCSV(file);
return getObj(listField,resultStrList,c,hasHeader);
}
/**
* 将从文件中读取到的字符串列表 转换成对象列表
* @param listField 属性列表
* @param resultStrList 从文件中读取到的字符串列表
* @param c 类
* @param hasHeader 是否有表头
* @return 对象列表
*/
private static List<Object> getObj(List<String> listField, List<String> resultStrList, Class c, boolean hasHeader) {
int fieldNum = listField.size();
List<Object> objectList = new ArrayList<>();
//根据是否有表头来确定从哪个下标开始读取数据
int index = hasHeader ? fieldNum : 0;
for (; index < resultStrList.size();index += fieldNum){
try {
Object o = c.newInstance();
for (int j = 0;j < fieldNum;j ++){
if (index + j < resultStrList.size()){
String dataStr = resultStrList.get(index + j);
if(StringUtils.isNotBlank(dataStr)){
String filedName = listField.get(j);
//为对象的该属性设置值
setValueForObject(c,o,filedName,dataStr);
}
}
}
objectList.add(o);
} catch (Exception e){
e.printStackTrace();
}
}
return objectList;
}
/**
* 为对象设置属性值
* @param c Class对象
* @param o 要设置属性值的对象
* @param filedName 属性名
* @param dataStr 字符串类型的数据值
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
private static void setValueForObject(Class c, Object o, String filedName, String dataStr) throws IllegalAccessException, InvocationTargetException {
String methodName = getSetterMethodName(filedName);
Method[] methods = c.getDeclaredMethods();
for (Method method : methods){
if (methodName.equals(method.getName())){
Class<?>[] paramTypes = method.getParameterTypes();
//获取到参数的类型全限定名
String paramTypeName = paramTypes[0].getName();
//将字符串类型数据值转换成对应类型的数据
Object data = typeConversion(paramTypeName,dataStr);
method.invoke(o,data);
break;
}
}
}
/**
* 将字符串类型的数据值转换为所需的对象
* @param paramTypeName 所需参数类型的全限定名
* @param dataStr 字符串类型的数据值
* @return 转换得到的对象
*/
private static Object typeConversion(String paramTypeName, String dataStr) {
if (paramTypeName.contains("Integer")){
int index = dataStr.indexOf(".");
if (index > 0){
dataStr = dataStr.substring(0,index);
}
}
try{
Class<?> paramClass = Class.forName(paramTypeName);
Constructor<?> constructor = paramClass.getConstructor(String.class);
Object o = constructor.newInstance(dataStr);
return o;
} catch (Exception e){
e.printStackTrace();
}
return null;
}
/**
* 根据属性名获取它的setter方法的名称
* @param filedName 属性名
* @return 属性对应的setter方法名
*/
private static String getSetterMethodName(String filedName) {
StringBuilder sb = new StringBuilder();
sb.append("set");
return sb.append(titleCase(filedName)).toString();
}
/**
* 首字母大写
* @param s 要进行转换的字符串
* @return 首字母大写后的结果
*/
private static String titleCase(String s) {
char[] chars = s.toCharArray();
if(chars[0] >= 97 && chars[0] <= 122){
chars[0] -= 32;
}
return String.valueOf(chars);
}
/**
* 读取CSV文件
* @param file 文件
* @return 得到的文件中的字符串集合
*/
public static List<String> readCSV(File file){
List<String> resultStrList = new ArrayList<>();
try(BufferedReader bufferedReader = new BufferedReader(new FileReader(file))){
String line = null;
String[] items = null;
while((line = bufferedReader.readLine()) != null){
if(StringUtils.isNotBlank(line)){
items = line.split(",",Integer.MAX_VALUE);
resultStrList.addAll(Arrays.asList(items));
}
}
}catch (IOException e){
e.printStackTrace();
}
return resultStrList;
}
}
写一个工具类用来拿到由CSV内容转换成的对象,并对它做我们想要的处理(这里我就不处理了,仅仅把它遍历输出一下)
package ReadCSV.util;
import ReadCSV.dto.ExcelObj;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class ReadCSVAndWrite {
/**
* 读取CSV文件并转换成sql输出到指定文件中
* @param csvPath
* @param targetPath
*/
public static void readCSVAndWrite(String csvPath){
final File file = new File(csvPath);
List<String> fieldList = getListField();
List<ExcelObj> excelObjs = HPoiUtils.exeCsv(file,fieldList, ExcelObj.class);
for (ExcelObj excelObj : excelObjs){
System.out.println(excelObj);
}
}
/**
* 获取csv文件中的列名列表
* @return
*/
private static List<String> getListField(){
List<String> fieldList = new ArrayList<>();
fieldList.add("id1");
fieldList.add("id2");
return fieldList;
}
}
在main方法中执行一下看看
public static void main(String[] args) {
ReadCSVAndWrite.readCSVAndWrite("/Users/admin/Desktop/list/test.csv");
}
成功拿到我们想要的对象:
连对象都拿到了,对它进行我们想要的处理不是轻而易举了嘛~