用Java读取大文件

CC.*_*CC. 59 java memory-management file

我需要一个非常了解Java的人和内存问题的建议.我有一个大文件(类似1.5GB),我需要在许多(例如100个小文件)较小的文件中剪切此文件.

我一般都知道怎么做(使用a BufferedReader),但我想知道你是否有关于内存的任何建议,或者提示如何更快地完成它.

我的文件包含文本,它不是二进制文件,每行大约有20个字符.

Bal*_*usC 35

为了节省内存,不要在内存中不必要地存储/复制数据(即不要将它们分配给循环外的变量).只要输入进入,就立即处理输出.

无论你是否使用,这都无关紧要BufferedReader.一些隐含的暗示似乎不会花费更多的内存.它最高只会达到性能的几个百分点.这同样适用于使用NIO.它只会提高可扩展性,而不是内存使用.当你在同一个文件上运行数百个线程时,它才会变得有趣.

只需遍历文件,在读入时立即将每一行写入其他文件,计算行数,如果达到100,则切换到下一个文件,等等.

开球示例:

String encoding = "UTF-8";
int maxlines = 100;
BufferedReader reader = null;
BufferedWriter writer = null;

try {
    reader = new BufferedReader(new InputStreamReader(new FileInputStream("/bigfile.txt"), encoding));
    int count = 0;
    for (String line; (line = reader.readLine()) != null;) {
        if (count++ % maxlines == 0) {
            close(writer);
            writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("/smallfile" + (count / maxlines) + ".txt"), encoding));
        }
        writer.write(line);
        writer.newLine();
    }
} finally {
    close(writer);
    close(reader);
}
Run Code Online (Sandbox Code Playgroud)


Mic*_*rdt 29

首先,如果您的文件包含二进制数据,那么使用BufferedReader将是一个很大的错误(因为您将数据转换为String,这是不必要的并且可能很容易破坏数据); 你应该用一个BufferedInputStream代替.如果是文本数据并且您需要沿着换行符将其拆分,那么使用BufferedReader就可以了(假设文件包含合理长度的行).

关于内存,如果你使用一个体积适中的缓冲区应该没有任何问题(我使用至少1MB来确保HD主要进行顺序读取和写入).

如果速度证明是一个问题,你可以看看这些java.nio包 - 据说速度比java.io,

  • 另外,一个常见的误解是"nio"比"io"更快.在某些情况下可能是这种情况,但通常"nio"被写为比"io"更多_scalable_,其中"可伸缩"不一定与"更快"相同. (11认同)

Rya*_*rle 13

您可以考虑通过FileChannel使用内存映射文件.

通常对于大文件来说快得多.有性能权衡可以使它变慢,所以YMMV.

相关回答:Java NIO FileChannel与FileOutputstream的性能/实用性


b.r*_*oth 5

这是一篇很好的文章:http : //java.sun.com/developer/technicalArticles/Programming/PerfTuning/

总而言之,为了获得出色的性能,您应该:

  1. 避免访问磁盘。
  2. 避免访问基础操作系统。
  3. 避免方法调用。
  4. 避免单独处理字节和字符。

例如,要减少对磁盘的访问,可以使用大缓冲区。本文介绍了各种方法。