/**
* @author zjl
* @date 2023/3/23
*/
@Slf4j
public class CsvReadUtil {
private static Pattern humpPattern = Pattern.compile("[A-Z]");
public static final String REGEX1 = "\\D";
/**
* 通用方法
*
* @param filename 文件名
* @param splitChar 分隔符
* @param entity 实体映射
* @return
* @throws Exception
*/
public static <T> List<T> csvRead(String filename, String splitChar, Class<T> entity) throws Exception {
FileInputStream fileInputStream = new FileInputStream(filename);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream, StandardCharsets.UTF_8));
String titleStr = bufferedReader.readLine();
log.info("文件头=>{}", titleStr);
if (StringUtils.isEmpty(titleStr)) {
log.info("文件为空,结束解析=>{}", titleStr);
return new ArrayList<T>();
}
// 获取csv中的列名
List<String> titleList = new ArrayList<>();
List<String> tmpList = Arrays.asList(titleStr.split(splitChar));
// 驼峰命名,转成下划线
tmpList.forEach(str -> {
titleList.add(humpToLine(str));
});
log.info("文件中字段列表->{}", titleList);
Field[] declaredFields = entity.getDeclaredFields();
List<String> filedNames = Arrays.stream(declaredFields).map(Field::getName).collect(Collectors.toList());
// 获取排序后的实体类字段列表
List<String> columns = new ArrayList<>();
// 驼峰命名,转成下划线
filedNames.forEach(str -> {
columns.add(humpToLine(str));
});
log.info("实体类字段列表->{}", columns);
Map<Integer, Integer> filedTargetMap = getFiledTargetMap(columns, titleList);
List<T> entityList = new ArrayList<>();
String line;
AtomicInteger num = new AtomicInteger(1);
while (StringUtils.isNotEmpty(line = bufferedReader.readLine())) {
log.info("进行到第{}页", num.incrementAndGet());
String[] str = line.split(splitChar);
T pojo = entity.newInstance();
Field[] declaredFieldList = pojo.getClass().getDeclaredFields();
String finalLine = line;
filedTargetMap.forEach((columnIndex, titleIndex) -> {
String value = str[titleIndex];
/**
* 由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的
*/
declaredFieldList[columnIndex].setAccessible(true);
/**
* 通过反射 对 对象赋值
*/
try {
declaredFieldList[columnIndex].set(pojo, value);
} catch (IllegalAccessException e) {
e.printStackTrace();
log.error("错误的行{}, 内容为{}", num, finalLine);
return;
}
});
entityList.add(pojo);
}
return entityList;
}
/**
* 驼峰转下划线,最后转为小写
*
* @param str
* @return
*/
public static String humpToLine(String str) {
Matcher matcher = humpPattern.matcher(str);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(sb, "_" + matcher.group(0).toUpperCase());
}
matcher.appendTail(sb);
return sb.toString().toLowerCase();
}
/**
* 获取实体类字段对应csv中的下标值MAP
* columns 实体集合(驼峰命名,转成下划线)
* titleList 文件字段(驼峰命名,转成下划线)
*/
public static Map<Integer, Integer> getFiledTargetMap(List<String> columns, List<String> titleList) {
//前面实体索引,后面字段索引
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < columns.size(); i++) {
int index = titleList.indexOf(columns.get(i));
if (index >= 0) {
map.put(i, index);
}
}
return map;
}
}
Java CSV自定义实体对象读取工具类
最新推荐文章于 2024-06-24 16:24:19 发布