Java StringBuilder.append outofmemory

Java StringBuilder.append outofmemory,java,file,out-of-memory,stringbuilder,Java,File,Out Of Memory,Stringbuilder,我使用StringBuilder.append()解析和处理文件,如下所示: StringBuilder csvString = new StringBuilder(); bufferedReader.lines().filter(line -> !line.startsWith(HASH) && !line.isEmpty()).map(line -> line.trim()) .forEachOrd

我使用StringBuilder.append()解析和处理文件,如下所示:

        StringBuilder csvString = new StringBuilder();

        bufferedReader.lines().filter(line -> !line.startsWith(HASH) && !line.isEmpty()).map(line -> line.trim())
                .forEachOrdered(line -> csvString.append(line).append(System.lineSeparator()));

        int startOfFileTagIndex = csvString.indexOf(START_OF_FILE_TAG);

        int startOfFieldsTagIndex = csvString.indexOf(START_OF_FIELDS_TAG, startOfFileTagIndex);
        int endOfFieldsTagIndex = csvString.indexOf(END_OF_FIELDS_TAG, startOfFieldsTagIndex);

        int startOfDataTagIndex = csvString.indexOf(START_OF_DATA_TAG, endOfFieldsTagIndex);
        int endOfDataTagIndex = csvString.indexOf(END_OF_DATA_TAG, startOfDataTagIndex);

        int endOfFileTagIndex = csvString.indexOf(END_OF_FILE_TAG, endOfDataTagIndex);

        int timeStartedIndex = csvString.indexOf("TIMESTARTED", endOfFieldsTagIndex);
        int dataRecordsIndex = csvString.indexOf("DATARECORDS", endOfDataTagIndex);
        int timeFinishedIndex = csvString.indexOf("TIMEFINISHED", endOfDataTagIndex);

        if (startOfFileTagIndex != 0 || startOfFieldsTagIndex == -1 || endOfFieldsTagIndex == -1
                || startOfDataTagIndex == -1 || endOfDataTagIndex == -1 || endOfFileTagIndex == -1) {

            log.error("not in correct format");

            throw new Exception("not in correct format.");
        }
问题是,当文件相当大时,会出现outofmemoryexception。 你能帮我转换代码以避免大文件出现这种异常吗

编辑: 正如我所理解的,将一个巨大的文件放入字符串生成器不是一个好主意,也不会起作用。
因此,问题是Java中的哪种结构更适合用于解析我的大文件、删除一些行、查找一些行的索引并将文件分成多个部分(在哪里存储那些可能很大的部分)根据找到的索引,然后最终创建一个输出文件?

OOM似乎是由于您将所有行存储在
StringBuilder
中。当文件有太多行时,它将占用大量内存并可能导致OOM

避免这种情况的策略取决于您对附加字符串所做的操作。 正如我在代码中所看到的,您只是尝试验证输入文件的结构。在这种情况下,不需要将所有行存储在
StringBuilder
实例中。相反

  • 有多个
    int
    s来保存您感兴趣的每个索引(或者有一个
    int
    s数组)
  • 检测正在查找的“标记”或“索引”的存在,并将其保存在指定的
    int
    变量中,而不是将该行添加到
    StringBuilder
  • 最后,您正在执行的检查可能需要进行更改,以测试不是作为
    -1
    ,而是相对于其他索引。(这是您当前使用
    indexOf()调用中的开始索引实现的。)
  • 如果存在跨行标记的风险,则您可能无法使用流,但必须使用一个简单的
    for
    循环,在该循环中保存以前的一些行,附加它们并进行检查。(只有一个想法,你可能会有更好的想法。)

  • 您主要有两种选择:增加JVM可用的内存,或者逐个解析行而不存储它们。。。