【问题标题】:Messed up CSV leads to Exception搞砸 CSV 导致异常
【发布时间】:2012-11-27 14:02:16
【问题描述】:

我想我发现了一个错误。也可能不是,但 Super CSV 不能很好地处理。

我正在使用 MapReader 解析一个包含 41 列的 CSV 文件。但是,我得到了那个 CSV - 给我 CSV 的 Web 服务弄乱了一行。 “标题”行是一个以制表符分隔的行,有 41 个单元格。

“错误的行”是一个制表符分隔的行,有 36 个单元格,内容没有任何意义。

这是我正在使用的代码:


InputStream fis = new FileInputStream(pathToCsv);
InputStreamReader inReader = new InputStreamReader(fis, "ISO-8859-1");

ICsvMapReader mapReader = new CsvMapReader(inReader, new CsvPreference.Builder('"','\t',"\r\n").build());
final String[] headers = mapReader.getHeader(true);
Map<String, String> row;
while( (row = mapReader.read(headers)) != null ) {

    // do something


}

在上面提到的行中执行 mapReader.read(headers) 时出现异常。这是一个例外:

org.supercsv.exception.SuperCsvException: 
the nameMapping array and the sourceList should be the same size (nameMapping length = 41, sourceList size = 36)
context=null
at org.supercsv.util.Util.filterListToMap(Util.java:121)
at org.supercsv.io.CsvMapReader.read(CsvMapReader.java:79)
at test.MyClass.readCSV(MyClass.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)

你觉得我应该怎么做?

我不希望整个应用程序崩溃,只是因为某一行搞砸了,我宁愿跳过那一行。

【问题讨论】:

    标签: java csv supercsv


    【解决方案1】:

    这是个好问题!作为 Super CSV 开发人员,我将研究在 website 上创建一些异常处理示例。

    您可以保持简单并使用 CsvListReader(它不关心有多少列),然后自己创建 Map:

    public class HandlingExceptions {
    
        private static final String INPUT = 
            "name\tage\nTom\t25\nAlice\nJim\t44\nMary\t33\tInvalid";
    
        public static void main(String[] args) throws IOException {
    
            // use CsvListReader (can't be sure there's the correct no. of columns)
            ICsvListReader listReader = new CsvListReader(new StringReader(INPUT), 
                new CsvPreference.Builder('"', '\t', "\r\n").build());
    
            final String[] headers = listReader.getHeader(true);
    
            List<String> row = null;
            while ((row = listReader.read()) != null) {
    
                if (listReader.length() != headers.length) {
                    // skip row with invalid number of columns
                    System.out.println("skipping invalid row: " + row);
                    continue;
                }
    
                // safe to create map now
                Map<String, String> rowMap = new HashMap<String, String>();
                Util.filterListToMap(rowMap, headers, row);
    
                // do something with your map
                System.out.println(rowMap);
            }
            listReader.close();
        }
    }
    

    输出:

    {name=Tom, age=25}
    skipping invalid row: [Alice]
    {name=Jim, age=44}
    skipping invalid row: [Mary, 33, Invalid]
    

    如果您担心使用 Super CSV 的 Util 类(它可能会改变 - 它实际上是一个内部实用程序类),您可以按照我建议的 here 组合 2 个阅读器。

    您可以尝试捕获SuperCsvException,但您最终可能会抑制的不仅仅是无效的列数。我建议捕获的唯一 Super CSV 异常(尽管不适用于您的情况,因为您没有使用单元处理器)是 SuperCsvConstraintViolationException,因为它表明文件格式正确,但数据不满足您的要求预期的约束。

    【讨论】:

    • 感谢您的出色回答。附加信息:捕捉SuperCsvConstraintViolationException 是行不通的,因为它会抛出SuperCsvExceptionex instanceof SuperCsvConstraintViolationException 评估false
    • 是的,可以实现读取的重载,它包含一个被调用的对象,而不是引发异常。也许被调用的方法将异常作为参数,因此由提供的方法决定是否抛出或忽略错误
    • 抱歉 @steve 这只是关于 SuperCsvConstraintViolationException 的一般建议 - 不适用于您的场景,因为您没有使用单元处理器!
    • 好的,无论如何谢谢 :) 只是想说清楚,以防其他人有这个“问题”。
    【解决方案2】:

    如果 CSV 文件包含无法解析的数据,您必须问自己该怎么办。跳过这些行有多重要。在一种情况下,可以直接删除它,而在其他情况下,最好停止整个过程并告诉用户先修复文件。

    我相信您可以使用 Super CSV 构建这两种场景。您肯定必须处理该异常并对上述场景做出适当的反应。

    【讨论】:

      【解决方案3】:

      好吧,我想出了一些解决方案,但我认为它不是最佳的。

      while (true) {
          try {
              if ((row = mapReader.read(headers)) == null) {
                  break;
              } else {
                  // do something
              }
          } catch (SuperCsvException ex) {
              continue;
          }
      }
      

      更新

      Exception 更改为SuperCsvException

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-08-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-18
        相关资源
        最近更新 更多