我有一个大文本文件,但没有任何换行符。它只包含一个长字符串(1个字符串的大字符串,包含所有ASCII字符),但到目前为止,任何工作都可以正常,因为我可以用Java读取整行到内存中,但我想知道是否有内存泄漏问题,因为文件变得像5GB +那么大,并且程序无法立即将整个文件读入内存,所以在这种情况下读取此类文件的最佳方法是什么?我们可以将这条巨大的线分成两部分甚至多块吗?
以下是我阅读文件的方式
BufferedReader buf = new BufferedReader(new FileReader("input.txt"));
String line;
while((line = buf.readLine()) != null){
}
答案 0 :(得分: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。
答案 1 :(得分:3)
不会有任何内存泄漏,因为JVM有自己的垃圾收集器。但是,您可能会耗尽堆空间。
在这种情况下,最好以可管理的方式导入和处理流。读入64MB左右并重复。
您还可能会发现将-Xmx
参数添加到java
调用中非常有用,以便增加JVM中可用的最大堆空间。
答案 2 :(得分: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
}
答案 3 :(得分:0)
除了读取块的想法之外,您还可以使用java.nio.MappedByteBuffer查看文件的内存映射区域。您仍将被限制为最大缓冲区大小Integer.MAX_VALUE。如果您要在一个块中进行分散访问,这可能比明确读取块更好。
答案 4 :(得分: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);
}
答案 5 :(得分:-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
}
}