将大文件读取到数组java.lang.OutOfMemoryError:Java堆空间

时间:2014-04-17 19:16:18

标签: java for-loop out-of-memory bufferedreader

我正在尝试将极大的文件读取到数组中。很明显,我现在不是把它读成阵列,但这不是我遇到的问题。 它大约有6亿个数字,这似乎导致它出错。 线程" main"中的例外情况java.lang.OutOfMemoryError:Java堆空间

BufferedReader brWorld = null;
String World;
brWorld = new BufferedReader(new FileReader("Saves/" + Name));
World = brWorld.readLine();
String Numbers = World;
String[] LoadWorld = Numbers.split("");
for(int x = 0; x < MaterialArray.length * MaterialArray.length; x++){
    System.out.println(String.valueOf(LoadWorld[x]));
}

我将一个遗嘱加载到我的游戏阵列中。 有没有办法加载这么大的文本文件? 谢谢Liam

2 个答案:

答案 0 :(得分:3)

首先,你需要大量的内存。几GB的RAM,不包括GC室。

如果您正在阅读&#34;单行&#34;最后,在实际读取该行之后的600M数字(你甚至可能没有达到这个目的),600M数字的字符串将需要1.2GB的内存,仅用于字符。

Java将字符串存储为字符数组,字符存储在内部为UTF-16,即2个字节。

仅此一项就可以通过屋顶发送内存要求。

当您进行拆分时,您将每个数字转换为单个字符串。你现在拥有600M Strings,以及所有需要的头脑。至少,每个字符串至少要查找16个字节,因为它将指针存储到底层数组,数组中的偏移量以及字符串的长度。值得庆幸的是,split实际上会重用底层数组,但这对我们来说真的没什么帮助。

16字节* 600M是9.6GB。

绝对要进入&#34;荒唐的&#34;现在的内存需求领域。

你不能说出你真正想做的事情。你想加载文件&#34;但是你不会说什么。因此,很难就如何做到这一点提出建议。如果您只想打印文件,那么您可以逐个阅读每个字符并打印出来,但这显然不是目标。

所以,虽然,是的,你可以&#34;抛出记忆&#34;在这个问题上,你不想。你需要研究这个问题,并提出一个更好的代表,你要从那里实现和工作。

答案 1 :(得分:0)

这就是你内存不足的原因:

brWorld = new BufferedReader(new FileReader("Saves/" + Name));
World = brWorld.readLine();
String Numbers = World;
String[] LoadWorld = Numbers.split("");

您首先阅读所有数字:

600,000,000 chars = 600,000,000 bytes = 600 MB

所以你至少已经达到了600MB。然后,您将创建一个全新的字符串数组。这意味着您要为数组中的每个char创建一个String指针。根据您的体系结构,这可能是4个字节或更多:

600 MB + 600,000,000 * 4 = 600 MB + 2,400 MB = 3,000 MB = 3 GB

*这些数字是估计值,我知道实际数量可能更大。

如您所见,这根本不是一个可行的解决方案。这是一个更好的解决方案:

BufferedReader brWorld = null;
String world;
brWorld = new BufferedReader(new FileReader("Saves/" + Name));
world = brWorld.readLine();
for(int x = 0; x < MaterialArray.length * MaterialArray.length; x++){
    System.out.println(String.valueOf(world.charAt(x)));
}