Guava提供了LineProcessor接口,用于文件逐行读取、逐行处理,代码示例:
Files.asCharSource(file, Charsets.UTF_8).readLines(new LineProcessor<String>() {
@Override
public boolean processLine(String line) throws IOException {
//每一行调用一次,返回false就会中断读取
return false;
}
@Override
public String getResult() {
//文件读取完成后返回
return null;
}
});
如果我们需要逐行读取,读取多行后一起处理一次(批量处理增加效率),Guava的工具类就不满足要求
?
public class FileUtil {
/**
* @param file 需要读取的文件 * @param charset 字符集编码 * @param concurrencyLevel 一次回调所读取的最大行数 * @param func 回调函数,建议内部捕获异常,返回false将中断读取 * @throws IOException 文件无法找到、文件读取失败异常
*/
public static void readFile(File file, Charset charset, int concurrencyLevel, Function<List<String>, Boolean> func) throws IOException {
List<String> lineList = new ArrayList<>();
FileInputStream fis = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fis, charset);
try (BufferedReader reader = new BufferedReader(isr)) {
String line = reader.readLine();
while (line != null) {
lineList.add(line);
if (lineList.size() >= concurrencyLevel) {
boolean runOn = func.apply(lineList);
lineList.clear();
if (!runOn) {
break;
}
}
//读下一行,判断是不是最后一行,最后一行要刷新处理一次
//文件逐行读取、每10行批量处理一次(文件末尾不足10行的也要处理一次)。
line = reader.readLine();
if (line == null && lineList.size() > 0) {
func.apply(lineList);
lineList.clear();
break;
}
}
}
}
}
使用
FileUtil.readFile(file, Charset.forName("UTF-8"), 10, list -> {
//每10行调用一次,返回false就会中断读取
//list 包含10行的文件内容
return true;
});