在Java读取一些较大的文件时,为了避免读取的流和存放数据的对象过大而导致OOM,可以采用分段读取的方式,按照自己定义的每段最大执行数,进行入库。
以下是一个示例
1.使用try-with-resources的方式,确保流被正确关闭,因为它是实现了AutoCloseable接口的资源
2.使用BufferedReader进行缓存,并逐行读取,减少内存消耗.
package com.epidemic.report.util;
import cn.hutool.json.JSONUtil;
import javax.swing.text.html.parser.Entity;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
* <Description> ******
*
* @author yuSen.zhang
* @version 1.0
* @date 2023/03/21
*/
public class FileIORead {
public static final int INSERT_MAX_NUM = 1000;
public void readFileToEntityAndSave() {
//isFirstInsert = 是否为第一次入库操作
boolean isFirstInsert = Boolean.TRUE;
String line;
try (FileInputStream fis = new FileInputStream(new File("C:\\你的文件全路径"));
BufferedReader br = new BufferedReader(new InputStreamReader(fis, StandardCharsets.UTF_8))) {
//起始数
int startNums = 0;
StringBuilder builder = new StringBuilder();
while ((line = br.readLine()) != null) {
builder.append(line).append(System.lineSeparator());
startNums++;
if (startNums == INSERT_MAX_NUM) {
//本次取到的分段字符去执行你的业务逻辑操作
coverTxtAndSave(builder.toString(), isFirstInsert);
//清空builder
builder.setLength(0);
//开始下一个分段
startNums = 0;
//表示不是第一次入库
isFirstInsert = Boolean.FALSE;
}
}
if (startNums > 0) {
coverTxtAndSave(builder.toString(), isFirstInsert);
}
} catch (Exception e) {
//可自行进行异常处理
System.out.println(e.getMessage());
}
}
private void coverTxtAndSave(String data, boolean isFirstInsert) {
//伪代码 这里转为什么数据,由实际业务场景决定
List<Entity> entities = JSONUtil.toList(JSONUtil.parseArray(data), Entity.class);
//如果不是全量入库的话,这行代码可以删除
if (isFirstInsert) {
yourService.remove(new QueryWrapper<>());
}
//执行本次批量入库操作
yourService.saveBatch(entities);
}
}