为什么BufferedReader readLine读取超过EOF

时间:2016-06-13 23:10:36

标签: java file bufferedreader eof

我有一个非常大的文件(~6GB),其固定宽度文本由\ r \ n分隔,因此我使用缓冲读取器逐行读取。这个过程可以被中断或停止,如果是,它会使用一个检查点" lastProcessedLineNbr"快进到正确的地方继续阅读。这就是读者初始化的方式。

private void initializeBufferedReader(Integer lastProcessedLineNbr) throws IOException {
    reader = new BufferedReader(new InputStreamReader(getInputStream(), "UTF-8"));
    if(lastProcessedLineNbr==null){lastProcessedLineNbr=0;}

    for(int i=0; i<lastProcessedLineNbr;i++){
        reader.readLine();
    }
    currentLineNumber = lastProcessedLineNbr;
}

这似乎工作正常,我在这个方法中读取和处理数据:

public Object readItem() throws Exception {
    if((currentLine = reader.readLine())==null){
        return null;
    }
    currentLineNumber++;
    return parse(currentLine);
}

再一次,一切正常,直到我到达文档的最后一行。后一种方法中的readLine()会抛出错误:

17:06:49,980 ERROR [org.jberet] (Batch Thread - 1) JBERET000007: Failed to run job ProdFileRead, parse, org.jberet.job.model.Chunk@3965dcc8: java.lang.OutOfMemoryError: Requested array size exceeds VM limit
    at java.util.Arrays.copyOf(Arrays.java:3332)
    at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:137)
    at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:121)
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:569)
    at java.lang.StringBuffer.append(StringBuffer.java:369)
    at java.io.BufferedReader.readLine(BufferedReader.java:370)
    at java.io.BufferedReader.readLine(BufferedReader.java:389)
    at com.rational.batch.reader.TextLineReader.readItem(TextLineReader.java:55)

奇怪的是,它似乎是在文件末尾读取并分配了太多空间以至于内存不足。我尝试使用Cygwin和&#34; tail file.txt&#34;查看文件的内容。在控制台中它给了我预期的10行。但是当我做了&#34; tail file.txt&gt; output.txt的&#34; output.txt最终变为1.8GB,远远超过我预期的10行。所以看来Cygwin正在做同样的事情。据我所知,没有特殊的EOF角色。它只是数据的最后一个字节,它突然结束。

任何人都知道如何让这个工作?我想我可以计算读取的字节数,直到我得到文件的完整大小,但我希望有更好的方法。

1 个答案:

答案 0 :(得分:1)

  

但当我做tail file.txt > output.txt时,output.txt最终变为1.8GB,远远超过我预期的10行

这对我来说是文件填充了1.8GB的二进制零,当写入终端时,Cygwin的tail命令被忽略,但是Java没有忽略。这也可以解释您的OutOfMemoryError,因为BufferedReader继续阅读数据,寻找下一个\r\n,在溢出内存之前永远找不到它。