读取大型管道分隔值文件时超出GC开销限制

时间:2017-06-08 10:05:09

标签: java parsing delimiter large-files

我正在尝试解析一个大文件(650万行),但我得到了提到的内存不足错误。我使用相同的方法来读取大约50K行的其他文件,并且它的工作速度相当快。它运行得非常慢,然后失败并出现错误。我最初有2 GB专用于intelliJ,我改为4 GB(-Xmx4000m),然后是6 GB(-Xmx6000m),仍然完成相同的错误。我的电脑只有8 GB RAM,所以我不能再高了。有什么建议吗?

谢谢!

public static List<UmlsEntry> umlsEntries(Resource resource) throws 
 IOException {
 return CharStreams.readLines(new InputStreamReader(resource.getInputStream())).stream().distinct()
    .map(UmlsParser::toUmlsEntry).collect(Collectors.toList());
}

private static UmlsEntry toUmlsEntry(String line) {
 String[] umlsEntry = line.split("|");

 return new UmlsEntry(umlsEntry[UNIQUE_IDENTIFIER_FOR_CONCEPT_COLUMN_INDEX],
    umlsEntry[LANGUAGE_OF_TERM_COLUMN_INDEX], umlsEntry[TERM_STATUS_COLUMN_INDEX],
    umlsEntry[UNIQUE_IDENTIFIER_FOR_TERM_COLUMN_INDEX], umlsEntry[STRING_TYPE_COLUMN_INDEX],
    umlsEntry[UNIQUE_IDENTIFIER_FOR_STRING_COLUMN_INDEX],
    umlsEntry[IS_PREFERRED_STRING_WITHIN_THIS_CONCEPT_COLUMN_INDEX],
    umlsEntry[UNIQUE_IDENTIFIER_FOR_ATOM_COLUMN_INDEX], umlsEntry[SOURCE_ASSERTED_ATOM_INDENTIFIER_COLUMN_INDEX],
    umlsEntry[SOURCE_ASSERTED_CONCEPT_IDENTIFIER_COLUMN_INDEX],
    umlsEntry[SOURCE_ASSERTED_DESCRIPTOR_IDENTIFIER_COLUMN_INDEX],
    umlsEntry[ABBREVIATED_SOURCE_NAME_COLUMN_IDENTIFIER_COLUMN_INDEX],
    umlsEntry[ABBREVIATION_FOR_TERM_TYPE_IN_SOURCE_VOCABULARY_COLUMN_INDEX],
    umlsEntry[MOST_USEFUL_SOURCE_ASSERTED_IDENTIFIER_COLUMN_INDEX], umlsEntry[STRING_COLUMN_INDEX],
    umlsEntry[SOURCE_RESTRICTION_LEVEL_COLUMN_INDEX], umlsEntry[SUPPRESSIBLE_FLAG_COLUMN_INDEX],
    umlsEntry[CONTENT_VIEW_FLAG_COLUMN_INDEX]);
 }

1 个答案:

答案 0 :(得分:1)

您需要一次处理几行以避免耗尽所有可用内存,因为该文件不适合内存。 CharStreams.readLines令人困惑的不是流媒体。它一次读取所有行并返回一个列表。这不行。请尝试使用File.lines。我怀疑你也会遇到distinct的麻烦。它需要跟踪所有线条的所有哈希值,如果这个气球太过分,你可能也需要改变这种策略。哦,如果没有足够的内存来保存结果,collect将无效。然后,您可能希望写入新文件或数据库等。

以下是如何从文件中流式传输线条,计算不同的条目以及打印每行的md5的示例:

Files.lines(FileSystems.getDefault().getPath("/my/file"))
            .distinct()
            .map(DigestUtils::md5)
            .forEach(System.out::println);

如果您在检测不同行时遇到问题,请先将文件排在原位,然后仅过滤掉相同的相邻行。