3

Apache Commons CSV项目非常适合解析逗号分隔值、制表符分隔的数据和类似的数据格式。

我的印象是这个工具完全读取一个文件,结果行对象保存在内存中。但我不确定,我找不到任何关于这种行为的文档。

对于非常大的解析,我想进行增量读取,一次一行,或者一次可能相对少量的行,以避免压倒性的内存限制。

仅就内存使用而言,这里的想法类似于 XML 的 SAX 解析器如何增量读取以最小化 RAM 的使用,而 DOM 样式的 XML 解析器将文档完全读入内存以提供树遍历。

问题:

  • Apache Commons CSV 在读取文档方面的默认行为是什么:完全进入内存,还是增量?
  • 可以在增量文档和整个文档之间更改此行为吗?
4

1 回答 1

6

我的印象是这个工具完全读取一个文件,结果行对象保存在内存中

不会。内存的使用取决于您选择与CSVParser对象交互的方式。

JavadocCSVParser明确地解决了这个问题,在其Parsing record wiseParsing into memory部分中,请注意:

根据输入,解析到内存可能会消耗大量系统资源。例如,如果您正在解析 150MB 的 CSV 数据文件,则内容将完全读入内存。

我快速浏览了源代码,实际上解析记录似乎是一次从其输入源读取一个块,而不是一次全部读取。不过自己看吧

明智地解析记录

Parsing record wise一节中,它展示了如何CSVRecord通过循环Iterablethat is来一次递增地读取一个CSVParser

CSVParser parser = CSVParser.parse(csvData, CSVFormat.RFC4180);
for (CSVRecord csvRecord : parser) {
    ...
}

解析到内存

相比之下,解析到内存部分显示了使用CSVParser::getRecords将所有CSVRecord对象一次List全部加载到内存中。所以很明显,一个非常大的输入文件可能会耗尽一台受限机器上的内存。

Reader in = new StringReader("a;b\nc;d");
CSVParser parser = new CSVParser(in, CSVFormat.EXCEL);
List<CSVRecord> list = parser.getRecords();
于 2019-06-03T20:38:03.253 回答