这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战
前言
文件处理大家不模式,各种格式文件处理,文件流处理,和一些常用的文件服务器等待。今天给大家介绍一下Hutool结合, 函数式接口@FunctionalInterface 实现文件行处理器。
案例
再次安利一下Hutool 这个工具, 业务工程搭建必备, 减少很多开发的工作量和一些工具类封装不完善导致的一些坑。 业务场景, 文件读写,源文件的格式有xls, xlsx, txt, csv,输出文件格式有csv和xlsx格式,在解析文件的同时我们需要同时去写缓存,写Hbase等等一系列操作。 用@FunctionalInterface 方法可以使得代码更加简洁,易于封装。
传统的遍历方法
File sourceFile = new File(sourcePath);
BufferedReader reader = null;
try {
reader = FileUtil.getReader(sourceFile, EncodingDetect.getJavaEncode(sourcePath));
String line;
int index = 0;
while (true) {
line = reader.readLine();
if (line == null ) {
}
}
.......
}
函数式接口@FunctionalInterface
@FunctionalInterface
public interface LineHandler {
/**
* 处理一行数据,可以编辑后存入指定地方
* @param line 行
*/
void handle(String line);
}
File sourceFile = new File(sourcePath);
String lineSeparator = getLineSeparator(fileName)
List<String> contentList = new ArrayList<>(50000);
try {
FileUtil.readLines(sourceFile, Charset.forName(EncodingDetect.getJavaEncode(sourcePath)), (LineHandler) line ->{
if (line == null) {
return;
}
// 业务逻辑处理
});
if (CollectionUtils.isNotEmpty(contentList)) {
// 业务逻辑处理
contentList.clear();
}
} catch (Exception e) {
log.error("check exception, context:{}", JSON.toJSONString(context), e);
throw new AppException(ErrorCodeEnum.SYSTEM_ERROR);
}
Excel安全模式读写
我们知道Excel文件读写很容易导致内存溢出,Hutool 也封装了一些常用的操作
BigExcelWriter bigExcelWriter = ExcelUtil.getBigWriter(destPath);
List<Put> putList = new ArrayList<>(1000);
AtomicInteger index = new AtomicInteger();
try {
ExcelUtil.readBySax(new File(context.getSourcePath()), -1 , (i, i1, list) -> {
if (CollectionUtils.isEmpty(list) ) {
return;
}
// 业务逻辑处理
}
看下ExcelUtil#readBySax 源码
/**
* 通过Sax方式读取Excel,同时支持03和07格式
*
* @param file Excel文件
* @param rid sheet rid,-1表示全部Sheet, 0表示第一个Sheet
* @param rowHandler 行处理器
* @since 3.2.0
*/
public static void readBySax(File file, int rid, RowHandler rowHandler) {
final ExcelSaxReader<?> reader = ExcelSaxUtil.createSaxReader(ExcelFileUtil.isXlsx(file), rowHandler);
reader.read(file, rid);
}
RowHandler 源码
@FunctionalInterface
public interface RowHandler {
/**
* 处理一行数据
*
* @param sheetIndex 当前Sheet序号
* @param rowIndex 当前行号,从0开始计数
* @param rowList 行数据列表
*/
void handle(int sheetIndex, long rowIndex, List<Object> rowList);
/**
* 处理一个单元格的数据
*
* @param sheetIndex 当前Sheet序号
* @param rowIndex 当前行号
* @param cellIndex 当前列号
* @param value 单元格的值
* @param xssfCellStyle 单元格样式
*/
default void handleCell(int sheetIndex, long rowIndex, int cellIndex, Object value, CellStyle xssfCellStyle) {
//pass
}
/**
* 处理一个sheet页完成的操作
*/
default void doAfterAllAnalysed() {
//pass
}
}
最后
@FunctionalInterface 还是那句话Lambda表达式写法各有利弊, 一切的技术选型都是合适为主