我正在使用 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
实例中。相反,
- 有多个
int
来保存您感兴趣的每个索引,(或有一个int
数组) - 不要将行添加到
StringBuilder
中,而是检测您要查找的“标签”或“索引”是否存在,并将其保存在其指定的int
变量中. - 最后,您已经进行的检查可能需要进行更改,以便不是以
-1
进行测试,而是相对于其他索引进行测试。 (您目前正在使用indexOf()
调用中的起始索引来实现这一点。) - 如果标签存在跨行的风险,那么您可能无法使用流,而必须使用简单的
for
循环来保存一些先前的行,追加他们并检查。 (只是一个想法;您可能有更好的想法。)
关于java - StringBuilder.append 内存不足,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60298211/