【问题标题】:How can I process a large file via CSVParser?如何通过 CSVParser 处理大文件?
【发布时间】:2015-11-14 10:24:10
【问题描述】:

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

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

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

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

在上述情况下,如何解析单行(表头已知)?

【问题讨论】:

    标签: java csv filtering large-files apache-commons-csv


    【解决方案1】:

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

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

    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】:

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

      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
      

      【讨论】:

        猜你喜欢
        • 2010-12-28
        • 2016-06-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-09
        相关资源
        最近更新 更多