我正在编写一个程序,需要读取非常大的文件(大约 150Mb 的文本)。当我尝试读取大于 50Mb 的文件时,遇到内存不足错误。这是我的代码的摘录。
if (returnVal == JFileChooser.APPROVE_OPTION) {
file = fc.getSelectedFile();
gui.setTitle("Fluent Helper - " + file.toString());
try{
scanner = new Scanner(new FileInputStream(file));
gui.getStatusLabel().setText("Reading Faces...");
while(scanner.hasNext()){
count++;
if(count<1000000){
System.gc();
count = 0;
}
readStr = scanner.nextLine()+ "\n";
if(readStr.equals("#\n")){
isFaces = false;
gui.getStatusLabel().setText("Reading Cells...");
}else if(isFaces){
faces.add(new Face(readStr));
}else{
cells.add(new Cell(readStr));
}
}
}catch (Exception e){
e.printStackTrace();
}finally{
try{
scanner.close();
}catch(Exception e){
e.printStackTrace();
}
}
System.out.println("flie selected");
} else {
System.out.println("file not selected");
}
每次任意数量的读取都会调用垃圾收集器的小块是我为了解决内存问题而添加的,但它不起作用。相反,程序会挂起并且永远不会到达文件的单元格部分(这应该在不到一秒的时间内发生)。这是 block 。
if(count<1000000){
System.gc();
count = 0;
}
我的猜测是,扫描仪的指针可能正在被垃圾收集或其他什么。我真的没有任何线索。使用更大的堆启动程序对我来说并不是一个真正的选择。该程序应该可以被没有太多计算机知识的人使用。
我想要一种能够毫无问题地获取文件的解决方案,无论是内存管理解决方案还是修复扫描仪或更有效的读取文件的方法。谢谢大家。
最佳答案
GC 将在需要时自动调用,因此您自己调用它只会减慢应用程序的速度。
问题在于您保留的数据量
faces.add(new Face(readStr));
}else{
cells.add(new Cell(readStr));
这些超出了最大堆的内存量。您可以尝试设置 -mx1g
来看看这是否会产生影响?
顺便说一句:为什么要在每行末尾添加 \n
?
关于java - 读取大型文本文件、垃圾收集器和 Scanner 对象的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11051599/