搞砸了CSV会导致exception

我想我发现了一个bug。 或许它不是,但Super 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 row; while( (row = mapReader.read(headers)) != null ) { // do something } 

我在上面提到的行中执行mapReader.read(headers)时遇到exception。 这是例外:

 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) 

你觉得我应该怎么做 ?

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

这是一个很好的问题! 作为Super CSV开发人员,我将研究在网站上创建一些exception处理示例。

您可以保持简单并使用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 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 rowMap = new HashMap(); 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个读者,就像我在这里建议的那样。

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

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

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

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

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

UPDATE

使用SuperCsvException更改了Exception