我正在使用Commons CSV来解析与电视节目相关的CSV内容。其中一个节目的节目名称包含双引号;
116,6,2,29 9月10日,“”JJ“(60分钟)”,“http://www.tvmaze.com/episodes/4855/criminal-minds-6x02-jj”
显示的是“JJ”(60分钟),已经是双引号。这会在封装的标记和分隔符之间抛出IOException java.io.IOException:(第1行)无效的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分钟)” - 但有没有办法让公共CSV处理这个或做我需要手动修复此条目吗?
其他信息:其他节目名称在CSV条目中包含空格和逗号,并放在双引号内。
答案 0 :(得分:3)
这里的问题是引号没有被正确转义。你的解析器没有处理它。尝试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许可证)
答案 1 :(得分:1)
引用主要允许字段包含分隔符。如果字段中的嵌入式引号未转义,则无法使用,因此使用引号没有任何意义。如果您的示例值为“JJ”,60分钟,解析器如何知道逗号是该字段的一部分?数据格式无法可靠地处理嵌入式逗号,因此如果您希望能够这样做,最好更改源以生成符合RFC的csv格式。
否则,看起来数据源只是围绕带引号的非数字字段,并用逗号分隔每个字段,因此解析器需要执行相反的操作。您应该只是将数据视为逗号分隔,并使用removeStart / removeEnd自行删除前导/尾随引号。
您可以使用CSVFormat .withQuote(null),或者忘掉它,只使用String .split(',')
答案 2 :(得分: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"]
答案 3 :(得分:0)
您可以使用withEscape('\\')忽略引号内的引号
CSVFormat csvFormat = CSVFormat.DEFAULT.withEscape('\\')
参考:https://commons.apache.org/proper/commons-csv/apidocs/org/apache/commons/csv/CSVFormat.html
答案 4 :(得分: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 已经实现了这一点。