java - StringBuilder.append 内存不足

标签 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())
                .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.");
        }

问题是,当文件很大时,我会遇到内存不足异常。 您能帮我转换代码以避免大文件出现异常吗?

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

最佳答案

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

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

  1. 有多个 int 来保存您感兴趣的每个索引,(或有一个 int 数组)
  2. 不要将行添加到 StringBuilder 中,而是检测您要查找的“标签”或“索引”是否存在,并将其保存在其指定的 int 变量中.
  3. 最后,您已经进行的检查可能需要进行更改,以便不是以 -1 进行测试,而是相对于其他索引进行测试。 (您目前正在使用 indexOf() 调用中的起始索引来实现这一点。)
  4. 如果标签存在跨行的风险,那么您可能无法使用流,而必须使用简单的 for 循环来保存一些先前的行,追加他们并检查。 (只是一个想法;您可能有更好的想法。)

关于java - StringBuilder.append 内存不足,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60298211/

相关文章:

java - 如何统计给定长度的所有可能的二进制子串的数量?

java - java程序运行60M或90M正常吗?

java - 如何在 JavaPairRDD 上使用 max 方法

javascript - 文件输入我做错了什么?

java - 如何在android中找到可以用MediaPlayer播放的文件

java - 加载图像时出现内存不足错误

java - 监听器拒绝连接并出现以下错误 : ORA-12514

java.security.AccessControlException : access denied in Java RMI Telephone Directory

java - spring security 忽略authentication-failure-url

php - Errno=9 错误的文件描述符在 php 中