我在SO上发现了其他一些问题,这些问题与我的需求很接近,但我无法弄清楚。我正在逐行读取文本文件,并遇到内存不足错误。这是代码:
System.out.println("Total memory before read: " + Runtime.getRuntime().totalMemory()/1000000 + "MB");
String wp_posts = new String();
try(Stream<String> stream = Files.lines(path, StandardCharsets.UTF_8)){
wp_posts = stream
.filter(line -> line.startsWith("INSERT INTO `wp_posts`"))
.collect(StringBuilder::new, StringBuilder::append,
StringBuilder::append)
.toString();
} catch (Exception e1) {
System.out.println(e1.getMessage());
e1.printStackTrace();
}
try {
System.out.println("wp_posts Mega bytes: " + wp_posts.getBytes("UTF-8").length/1000000);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
System.out.println("Total memory after read: " + Runtime.getRuntime().totalMemory()/1000000 + "MB");
输出就像(在具有更多内存的环境中运行时):
Total memory before read: 255MB
wp_posts Mega bytes: 18
Total memory after read: 1035MB
请注意,比在生产环境中,我无法增加内存堆。
我尝试显式关闭流,执行gc并将流置于并行模式(消耗更多内存)。
我的问题是:
这是预期的内存使用量吗?
有没有办法使用更少的内存?
最佳答案
您的问题出在collect(StringBuilder::new, StringBuilder::append, StringBuilder::append)
中。将smth添加到StringBuilder
且内部数组不足时,请将其加倍并复制上一个的部分。
执行new StringBuilder(int size)
以预定义内部数组的大小。
第二个问题是您有一个大文件,但结果却将其放入StringBuilder
。这对我来说很奇怪。实际上,这与不使用String
将整个文件读入Stream
相同。