【问题标题】:Java CsvToBean.parse fails with Error parsing CSVJava CsvToBean.parse 失败,解析 CSV 时出错
【发布时间】:2015-10-21 16:00:16
【问题描述】:

我正在尝试在 Eclipse 中使用 OpenCSV 解析大型 CSV 文件。 这是 CSV 文件的前 4 条记录。完整文件有 219,590 条记录:-

0,23,1,0,someone@email.com,"Construction/Contractors/Contractors"
0,43,1,0,someone@email.com,"Engineering/Electrical Engineering/Electrical Engineering"
0,395,1,0,someone@email.com,"Sales/Sales Force Management/Sales Management"
0,398,1,0,someone@email.com,"Sales/Sales Strategy/Sales"

这是 Java 代码:-

    File csvFile = new File("data/userattrib2_30day.csv");
    ColumnPositionMappingStrategy strategy = new ColumnPositionMappingStrategy();
    strategy.setType(UserAttribRecord.class);
    String[] columns = new String[] {"userId", "attributeId", "rating", "timestamp", "email", "attributeDesc"};
    strategy.setColumnMapping(columns);

    CSVReader reader = new CSVReader(new FileReader(csvFile));
    CsvToBean<UserAttribRecord> csv = new CsvToBean<UserAttribRecord>();
    List<UserAttribRecord> userAttribList = csv.parse(strategy,reader);

它失败了:-

Exception in thread "main" java.lang.RuntimeException: Error parsing CSV!
at com.opencsv.bean.CsvToBean.parse(CsvToBean.java:95)
at com.opencsv.bean.CsvToBean.parse(CsvToBean.java:75)

我如何找出错误是什么?似乎没有任何调试信息,所以我不知道哪个记录中的哪个字段出现错误。我该如何调试? 谢谢

【问题讨论】:

    标签: java csv opencsv


    【解决方案1】:

    如果您可以自己构建它,请获取 opencsv 的主干构建。我已修改 CsvToBean 以打印出错误发生时它所在的行号。

    throw new RuntimeException("Error parsing CSV line: " + lineProcessed + " values: " + Arrays.toString(line), e);
    

    这将在 3.6 版本中发布,除非有任何问题,否则应该在感恩节之前发布。

    我很好奇导致这种情况的错误是什么。如果您进一步查看异常堆栈跟踪,您应该会看到“Caused by:”,这就是 CsvToBean 捕获的异常。鉴于您有超过 200k 行,我怀疑您遇到了内存不足异常 - 这意味着您需要将文件拆分为较小的文件,增加 JVM 的内存,或者使用在 3.5 版本中引入的 IterableCsvToBean允许逐行解析。

    希望对您有所帮助。

    :)

    【讨论】:

      【解决方案2】:

      我刚刚尝试使用univocity-parsers,我可以毫无问题地解析您的示例输入。试一试,因为它比 OpenCSV 快两倍(平均快 2 倍)。这是我的代码:

      首先将@Parsed 注释添加到要从 CSV 加载的字段(有很多可用选项,请查看文档)。

      public static class UserAttributeRecord{
      
          @Parsed
          int userId;
      
          @Parsed
          int attributeId;
      
          @Parsed
          int rating;
      
          @Parsed
          long timestamp;
      
          @Parsed
          String email;
      
          @Parsed
          String attributeDesc;
      }
      

      这是解析文件所需的代码:

      public static void main(String[] args) throws IOException{
      
          //creates a processor of java beans.
          BeanListProcessor<UserAttributeRecord> beanProcessor = new BeanListProcessor<UserAttributeRecord>(UserAttributeRecord.class);
      
          //then a settings object to configure the parser
          CsvParserSettings settings = new CsvParserSettings(); //many options here, check the tutorial
      
          //configures the parser to use the bean processor.
          settings.setRowProcessor(beanProcessor);
      
          //configures the input format.
          settings.setHeaders("userId", "attributeId", "rating", "timestamp", "email", "attributeDesc");
          settings.getFormat().setLineSeparator("\n");
      
          //creates a parser with your settings
          CsvParser parser = new CsvParser(settings);
      
          //parses everything. All rows are submitted to the row processor defined above
          parser.parseAll(new FileReader(new File("/path/to/file.csv")));
      
          //here's your list of beans
          List<UserAttributeRecord> beans = beanProcessor.getBeans();
      }
      

      披露:我是这个库的作者。它是开源免费的(Apache V2.0 许可)。

      【讨论】:

      • 在 Univocity-parsers 中,您如何一次获取单个记录(而不是列表)?因为鉴于他说完整文件有 219,590 条记录,我认为问题在于他的内存不足。请添加一个示例,显示从文件中单独读取记录。
      • 只需使用BeanProcessor(名称中不包含列表)。所有的 bean 都将被传递给一个名为 beanParsed 的回调方法。这个数量的bean不足以淹没内存。消耗 100MB 内存是不够的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-03
      • 2019-05-23
      • 2014-12-30
      • 2016-12-31
      • 1970-01-01
      • 1970-01-01
      • 2020-03-15
      相关资源
      最近更新 更多