如何使用Nio2读取大文件

时间:2013-05-20 12:12:26

标签: java file-io nio2 fileutils

我正在尝试阅读一个文本文件,该文件目前有大约3万行。

我怎么读?

我正在使用java.io.BufferedReader

阅读

这是一个代表我的方法的小代码片段。

int lineNumber = 1;
BufferedReader br = null;
String currentLine = null;
br = new BufferedReader(new FileReader(f));//here f will be the file name to be read, I have passed
while ((cuurentLine = br.readLine()) != null) {
  //here I have written logic to do processing after reading 1000 lines
  //line number = 1001 start processing, similarly it reads next 1000 lines, each line is put in a List collection
  //after reaching 1001 line clearing list and continuing the loop
}

我尝试过使用NIO2以下案例

br = Files.newBufferedReader(Paths.get(inputFileName), StandardCharsets.UTF_16);

导致了以下异常

exception :Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Unknown Source)
    at java.lang.AbstractStringBuilder.expandCapacity(Unknown Source)
    at java.lang.AbstractStringBuilder.ensureCapacityInternal(Unknown Source)
    at java.lang.AbstractStringBuilder.append(Unknown Source)
    at java.lang.StringBuffer.append(Unknown Source)
    at java.io.BufferedReader.readLine(Unknown Source)
    at java.io.BufferedReader.readLine(Unknown Source)
    at TexttoExcelMerger.readFileLineByLine(TexttoExcelMerger.java:66)
    at TexttoExcelMerger.main(TexttoExcelMerger.java:255)

首先,我的做法是对的吗?

在NIO2,apache FileUtils或任何其他API中是否有任何有效且快速的方法可以更快地读取文件,从而提高了我的文件读取率 过程更快。我可以读出像1000这样的前1000行 br.readFirst(1000);
但没有像我的逻辑那样逐行阅读或迭代?

2 个答案:

答案 0 :(得分:2)

将整个文件读入内存的任何方法都注定要失败。文件迟早会超过可用内存,程序将停止运行,必须完全重新设计。不是一个好的失败模式,因为用户在过渡期间无能为力。你正在那个时候割草。你甚至雄心勃勃地尝试使用包含数十万行的文件。一次重新思考并处理一条线。或者使用数据库。

NB不要自欺欺人。您正在使用java.io来读取该文件。这里的NIO2组件很少。并不是说你根本不需要它。

答案 1 :(得分:2)

内存不足异常

因为你试图将太多的文件读入内存,所以内存不足。这可能会以我能想到的两种方式发生。

你故意这样做

如果你试图保存你读过的每一行,那么你就会耗尽或记忆。

while ((curentLine = br.readLine()) != null) {
    stringBuilder.append(currentLine);
}

如果你只是想一次保存1000行,你可能只需用-Xmx来增加Java的堆大小即可。这一切都取决于1000行的内存占用量。

你不小心这样做了

如果您正在阅读的文件没有任何换行符,那么br.readLine()将尝试阅读整个内容,相信这是一条巨大的长行。

无需逐行阅读

如果您想象一个任意文本文件,它只是一长串字符。其中一些字符(EOL)对人类和许多程序具有特殊意义,但它们仍然只是字符。这意味着你不能只是说“给我第10行文本”而不​​阅读它前面的每个字符(因为你永远不知道你需要计算哪个字符EOL)。

可以使用固定长度的记录格式:你说每一行都是$ n $字符孤独(80,比如说)。现在,如果你想跳到第10行,你可以跳到第800个字符。但是,如果您实际使用的是UTF-16,那么字符不是char,这实际上并不起作用。

没关系,因为此时您可能应该使用数据库。