使用Commons CSV解析CSV -引号内的引号导致IOException

y53ybaqx  于 2022-12-06  发布在  其他
关注(0)|答案(5)|浏览(286)

我正在使用Commons CSV来解析与电视节目相关的CSV内容。其中一个节目的节目名称包含双引号;
116,6,2,29 9月10日,“JJ”(60分钟)",”http://www.tvmaze.com/episodes/4855/criminal-minds-6x02-jj
showname是“JJ”(60分钟),它已经在双引号中了。这将引发一个IOException java.io.IOException:(第1行)封装标记和分隔符之间字符无效。

ArrayList<String> allElements = new ArrayList<String>();
    CSVFormat csvFormat = CSVFormat.DEFAULT;
    CSVParser csvFileParser = new CSVParser(new StringReader(line), csvFormat);

    List<CSVRecord> csvRecords = null;

    csvRecords = csvFileParser.getRecords();

    for (CSVRecord record : csvRecords) {
        int length = record.size();
        for (int x = 0; x < length; x++) {
            allElements.add(record.get(x));
        }
    }

    csvFileParser.close();
    return allElements;

CSV格式.DEFAULT已使用引号('"')设置
我认为此CSV的格式不正确,“JJ”(60分钟)”应该是“JJ”(60分钟)-但是否有方法获得通用CSV来处理此问题,或者我是否需要手动修复此条目?
其他信息:其他节目名称在CSV条目中包含空格和逗号,并放在双引号内。

epfja78i

epfja78i1#

这里的问题是引号没有正确转义。你的解析器不能处理这个问题。试试univocity-parsers,因为这是我所知道的唯一一个可以处理带引号值中未转义引号的java解析器。它也比Commons CSV快4倍。试试下面的代码:

//configure the parser to handle your situation
CsvParserSettings settings = new CsvParserSettings();
settings.setUnescapedQuoteHandling(STOP_AT_CLOSING_QUOTE);

//create the parser
CsvParser parser = new CsvParser(settings);

//parse your line
String[] out = parser.parseLine("116,6,2,29 Sep 10,\"\"JJ\" (60 min)\",\"http://www.tvmaze.com/episodes/4855/criminal-minds-6x02-jj\"");

for(String e : out){
    System.out.println(e);
}

这将打印:

116
6
2
29 Sep 10
"JJ" (60 min)
http://www.tvmaze.com/episodes/4855/criminal-minds-6x02-jj

希望能有所帮助。
披露:我是这个库的作者,它是开源和免费的(Apache 2.0许可证)

yrdbyhpb

yrdbyhpb2#

引用主要是允许字段包含分隔符。如果字段中的嵌入式引号没有转义,这就不起作用,所以使用引号没有任何意义。如果你的示例值是“JJ”,60分钟,解析器如何知道逗号是字段的一部分?数据格式不能可靠地处理嵌入式逗号,所以如果你想做到这一点,最好更改源代码以生成符合RFC的csv格式。
否则,看起来数据源只是用引号将非数字字段括起来,并用逗号分隔每个字段,因此解析器需要执行相反的操作。您可能只需要将数据视为逗号分隔,并使用removeStart/removeEnd自己去掉前导/尾随引号。
您可以使用CSVFormat .withQuote(null),也可以不使用CSVFormat . withQuote(null),而只使用String .split(',')

6za6bjd0

6za6bjd03#

您可以使用withEscape('\')忽略引号中的引号
CSV格式= CSV格式.默认.带转义('\')
参考:https://commons.apache.org/proper/commons-csv/apidocs/org/apache/commons/csv/CSVFormat.html

hi3rlvi2

hi3rlvi24#

我认为在同一个标记中同时包含引号和空格会让解析器感到困惑。

CSVFormat csvFormat = CSVFormat.DEFAULT.withQuote('"').withQuote(' ');

这样应该就好了。

示例

对于输入行:

String line = "116,6,2,29 Sep 10,\"\"JJ\" (60 min)\",\"http://www.tvmaze.com/episodes/4855/criminal-minds-6x02-jj\"";

输出为(且不会掷回例外状况):

[116, 6, 2, 29 Sep 10, ""JJ" (60 min)", "http://www.tvmaze.com/episodes/4855/criminal-minds-6x02-jj"]
csbfibhn

csbfibhn5#

无需特殊解析器:只需在双引号前面加上一个双引号:

116,6,2,29 Sep 10,"""JJ"" (60 min)",...

RFC 4180中对此进行了详细说明

7.  If double-quotes are used to enclose fields, then a double-quote
   appearing inside a field must be escaped by preceding it with
   another double quote.  For example:

   "aaa","b""bb","ccc"

CSVFormat #DEFAULT已经实现了这一点。

相关问题