搞砸了CSV会导致异常

时间:2012-11-27 14:02:16

标签: java csv supercsv

我想我发现了一个错误。或许它不是,但超级CSV无法很好地处理。

我正在使用MapReader解析包含41列的CSV文件。但是,我正在获得CSV - 以及给我CSV的网络服务混乱了一行。 “标题”行是制表符分隔的行,包含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)

你认为我该怎么做?

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

3 个答案:

答案 0 :(得分:5)

这是一个很好的问题!作为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课程(它可能会改变 - 它实际上是一个内部实用工具类),您可以将2个读者合并为我已经建议here

您可以尝试捕获SuperCsvException,但最终可能会抑制的不仅仅是无效的列数。我建议捕获的唯一超级CSV例外(虽然不适用于您未使用过程处理器的情况)SuperCsvConstraintViolationException,因为它表示文件正确无误格式,但数据不满足您的预期约束。

答案 1 :(得分:1)

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

我相信您可以使用Super CSV构建这两种方案。您肯定必须处理该异常并对所提到的方案作出适当的反应。

答案 2 :(得分:0)

好吧,我提出了一些解决方案,但我认为这不是最佳选择。

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

<强>更新

使用Exception

更改了SuperCsvException
相关问题