7

我正在使用Commons CSV来解析与电视节目相关的 CSV 内容。其中一个节目的节目名称包含双引号;

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

节目名称是“JJ”(60 分钟),它已经用双引号括起来了。这是在封装的标记和分隔符之间抛出 IOException java.io.IOException: (line 1) invalid char。

    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;

CSVFormat.DEFAULT 已设置 withQuote('"')

我认为这个 CSV 的格式不正确,因为“”JJ“(60 分钟)”应该是“”“JJ”“(60 分钟)”——但是有没有办法让 commons CSV 来处理这个或者我需要手动修复这个条目?

附加信息:其他节目名称在 CSV 条目中包含空格和逗号,并放在双引号内。

4

5 回答 5

7

这里的问题是引号没有正确转义。您的解析器无法处理。尝试使用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 许可证)

于 2017-06-23T05:03:17.053 回答
2

引用主要允许字段包含分隔符。如果一个字段中嵌入的引号没有被转义,这是行不通的,所以使用引号没有任何意义。如果您的示例值为“JJ”,60 分钟,解析器如何知道逗号是字段的一部分?数据格式无法可靠地处理嵌入式逗号,因此如果您希望能够做到这一点,最好更改源以生成符合 RFC 的 csv 格式。

否则,看起来数据源只是用引号将非数字字段括起来,并用逗号分隔每个字段,因此解析器需要执行相反的操作。您可能应该将数据视为逗号分隔,并自己使用 removeStart/removeEnd 去除前导/尾随引号。

您可能会使用 CSVFormat .withQuote(null),或者忘记这一点而只使用 String .split(',')

于 2017-06-22T12:00:04.470 回答
2

您可以使用 withEscape('\\') 忽略引号内的引号

CSVFormat csvFormat = CSVFormat.DEFAULT.withEscape('\\')

参考:https ://commons.apache.org/proper/commons-csv/apidocs/org/apache/commons/csv/CSVFormat.html

于 2018-07-25T20:57:01.367 回答
0

我认为在同一个标​​记中同时包含引号和空格会使解析器感到困惑。尝试这个:

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"]
于 2017-06-22T11:37:29.120 回答
0

不需要特殊的解析器:只需在双引号前添加一个双引号:

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实现。

于 2021-02-22T13:16:54.427 回答