如何通过 CSVParser 处理大文件?

我有一个大文件(大约300 MB),从远程主机读取,并解析为目标文件,但我不需要将所有行复制到目标文件。在复制时,我需要从源中读取每一行,如果它传递了一些谓词,请将该行添加到目标文件中。.csv

我认为Apache CSV( )只能解析整个文件apache.commons.csv

CSVFormat csvFileFormat = CSVFormat.EXCEL.withHeader();
CSVParser csvFileParser = new CSVParser("filePath", csvFileFormat);
List<CSVRecord> csvRecords = csvFileParser.getRecords();

所以我不能使用.根据我的代码,应该为每行创建一个实例,这看起来效率低下。BufferedReadernew CSVParser()

在上面的情况下,如何解析一行(具有表的已知标题)?


答案 1

无论您做什么,文件中的所有数据都将传输到本地计算机,因为您的系统需要通过它进行解析以确定有效性。无论文件是通过解析器读取的文件到达的(以便您可以解析每行),还是只是出于解析目的复制整个文件,它都会转到本地。您需要将数据放在本地,然后修剪多余的数据。

调用已经是一场失败的战斗,因为文档解释说该方法将文件的每一行加载到内存中。要在节省活动内存的同时解析记录,您应该改为迭代每条记录;该文档意味着以下代码一次将一条记录加载到内存中:csvFileParser.getRecords()

CSVParser csvFileParser = CSVParser.parse(new File("filePath"), StandardCharsets.UTF_8, csvFileFormat);

for (CSVRecord csvRecord : csvFileParser) {
     ... // qualify the csvRecord; output qualified row to new file and flush as needed.
}

由于您解释说这不是本地的,因此上述解决方案容易由于连接问题而失败。为了消除连接问题,我建议您将整个远程文件复制到本地,通过比较校验和确保准确复制的文件,解析本地副本以创建目标文件,然后在完成后删除本地副本。"filePath"


答案 2

这是一个较晚的响应,但您可以将 与 CSVParser 一起使用:BufferedReader

try (BufferedReader reader = new BufferedReader(new FileReader(fileName), 1048576 * 10)) {
    Iterable<CSVRecord> records = CSVFormat.RFC4180.parse(reader);
    for (CSVRecord line: records) {
        // Process each line here
    }
catch (...) { // handle exceptions from your bufferedreader here