Hutool 文件处理高级特性

1,170 阅读2分钟

这是我参与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 ) {
        }
    }
    .......

}

image.png

函数式接口@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表达式写法各有利弊, 一切的技术选型都是合适为主