2

我有一个大文本文件,但没有任何换行符。它只包含一个长字符串(包含所有 ASCII 字符的一大行字符串),但到目前为止一切正常,因为我可以用 Java 将整行读入内存,但我想知道是否有内存泄漏问题,因为文件变得如此之大,如 5GB+ 并且程序无法一次将整个文件读入内存,那么在这种情况下,读取此类文件的最佳方法是什么?我们可以把这条巨大的线分成两部分甚至多块吗?

这是我阅读文件的方式

   BufferedReader buf = new BufferedReader(new FileReader("input.txt"));
   String line;
   while((line = buf.readLine()) != null){

   }
4

6 回答 6

9

单个字符串只能有 20 亿个字符长,每个字符将使用 2 个字节,因此如果您可以读取 5 GB 的行,它将使用 10 GB 的内存。

我建议你分块阅读文本。

Reader reader = new FileReader("input.txt");
try {
    char[] chars = new char[8192];
    for(int len; (len = reader.read(chars)) > 0;) {
        // process chars.
    }
} finally {
    reader.close();
}

无论文件大小如何,这将使用大约 16 KB。

于 2012-11-26T17:26:09.457 回答
3

不会有任何类型的内存泄漏,因为 JVM 有自己的垃圾收集器。但是,您可能会用完堆空间。

在这种情况下,最好将流导入和处理成可管理的部分。读取 64MB 左右并重复。

-Xmx您还可能会发现将参数添加到调用中很有用java,以便增加 JVM 中可用的最大堆空间。

于 2012-11-26T17:16:20.823 回答
1

最好以块的形式读取文件,然后将这些块连接起来或做任何你想做的事情,因为如果你正在阅读它是一个大文件,你会遇到堆空间问题

一种简单的方法,如下所示

  InputStream is;
  OutputStream os;

  byte buffer[] = new byte[1024];
  int read;
  while((read = is.read(buffer)) != -1)
  {
      // do whatever you need with the buffer
  }
于 2012-11-26T17:19:34.727 回答
0

除了分块读取之外,您还可以使用 java.nio.MappedByteBuffer 查看文件的内存映射区域。您仍将被限制为 Integer.MAX_VALUE 的最大缓冲区大小。如果您将在一个块中进行分散访问,这可能比显式读取块更好。

于 2012-11-26T17:41:27.797 回答
0

要从文件中读取块或将相同的内容写入某个文件,可以使用:

{
in = new FileReader("input.txt");
out = new FileWriter("output.txt");
char[] buffer = new char[1024];
int l = 0;
while ( (l = in.read(buffer)) > 0 ) {
    out.write(buffer, 0, l);
}
于 2017-11-19T03:39:05.307 回答
-1

您不会遇到任何内存泄漏问题,但可能会遇到堆空间问题。为避免堆问题,请使用缓冲区。

这完全取决于您当前阅读该行的方式。使用缓冲区可以避免所有堆问题。

public void readLongString(String superlongString, int size, BufferedReader in){
  char[] buffer = new char[size];
  for(int i=0;i<superlongString.length;i+=size;){
       in.read(buffer, i, size)
       //do stuff 
     }
}
于 2012-11-26T17:24:36.903 回答