我在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相同。

07-24 09:49
查看更多