当前位置: 首页 > 知识库问答 >
问题:

使用带引号字段内带有双引号的OpenCSV解析CSV

益稳
2023-03-14

我正在尝试使用OpenCSV解析CSV文件。其中一列以YAML序列化格式存储数据,并被引用,因为其中可以包含逗号。它里面也有引号,所以它通过放两个引号来转义。我能够在Ruby中轻松解析这个文件,但使用OpenCSV我无法完全解析它。这是一个UTF-8编码的文件。

这是我的Java片段,它试图读取文件

CSVReader reader = new CSVReader(new InputStreamReader(new FileInputStream(csvFilePath), "UTF-8"), ',', '\"', '\\');

这是此文件中的2行。第一行没有被正确解析,并且在"[公平贸易认证]"处被拆分,因为我猜是转义双引号。

1061658767,update,1196916,Product,28613099,Product::Source,"---
product_attributes:
-
- :name: Ornaments
  :brand_id: 49120
  :size: each
  :alcoholic: false
  :details: ""[Fair Trade Certified]""
  :gluten_free: false
  :kosher: false
  :low_fat: false
  :organic: false
  :sugar_free: false
  :fat_free: false
  :vegan: false
  :vegetarian: false
",,2015-11-01 00:06:19.796944,,,,,,
1061658768,create,,,28613100,Product::Source,"---
product_id:
retailer_id:
store_id:
source_id: 333790
locale: en_us
source_type: Product::PrehistoricProductDatum
priority: 1
is_definition:
product_attributes:
",,2015-11-01 00:06:19.927948,,,,,,

共有2个答案

燕翼
2023-03-14

按照Paul的建议,解决方案是使用与RFC4180兼容的CSV解析器。我使用了OpenCSV的CSVReader,但它不起作用,或者我无法让它正常工作。

我使用了FastCSV,一个RFC4180 CSV解析器,它可以无缝地工作。

File file = new File(csvFilePath);
CsvReader csvReader = new CsvReader();
CsvContainer csv = csvReader.read(file, StandardCharsets.UTF_8);
for (CsvRow row : csv.getRows()) {
    System.out.println(row.getFieldCount());  
}
呼延庆
2023-03-14

首先,我很高兴FastCSV为您工作,但我运行了可疑的子字符串,并通过3.9 openCSV运行了它,它与CsvParser和RFC4180Parser一起工作。请您详细介绍一下它是如何不解析的,并/或使用3.9 openCSV进行尝试,看看您是否遇到同样的问题,然后使用下面的配置进行尝试。

以下是我使用的测试:

CSVParser:

@Test
public void parseBigStringFromStackOverflowWithMultipleQuotesInLine() throws IOException {

    String bigline = "28613099,Product::Source,\"---\n" +
            "product_attributes:\n" +
            "-\n" +
            "- :name: Ornaments\n" +
            "  :brand_id: 49120\n" +
            "  :size: each\n" +
            "  :alcoholic: false\n" +
            "  :details: \"\"[Fair Trade Certified]\"\"\n" +
            "  :gluten_free: false\n" +
            "  :kosher: false\n" +
            "  :low_fat: false\n" +
            "  :organic: false\n" +
            "  :sugar_free: false\n" +
            "  :fat_free: false\n" +
            "  :vegan: false\n" +
            "  :vegetarian: false\n" +
            "\",,2015-11-01 00:06:19.796944";

    String suspectString = "---\n" +
            "product_attributes:\n" +
            "-\n" +
            "- :name: Ornaments\n" +
            "  :brand_id: 49120\n" +
            "  :size: each\n" +
            "  :alcoholic: false\n" +
            "  :details: \"[Fair Trade Certified]\"\n" +
            "  :gluten_free: false\n" +
            "  :kosher: false\n" +
            "  :low_fat: false\n" +
            "  :organic: false\n" +
            "  :sugar_free: false\n" +
            "  :fat_free: false\n" +
            "  :vegan: false\n" +
            "  :vegetarian: false\n" ;

    StringReader stringReader = new StringReader(bigline);

    CSVReaderBuilder builder = new CSVReaderBuilder(stringReader);
    CSVReader csvReader = builder.withFieldAsNull(CSVReaderNullFieldIndicator.BOTH).build();

    String item[] = csvReader.readNext();

    assertEquals(5, item.length);
    assertEquals("28613099", item[0]);
    assertEquals("Product::Source", item[1]);
    assertEquals(suspectString, item[2]);
}

RFC4180语法分析器

def 'parse big line from stackoverflow with complex string'() {
    given:
    RFC4180ParserBuilder builder = new RFC4180ParserBuilder()
    RFC4180Parser parser = builder.build()
    String bigline = "28613099,Product::Source,\"---\n" +
            "product_attributes:\n" +
            "-\n" +
            "- :name: Ornaments\n" +
            "  :brand_id: 49120\n" +
            "  :size: each\n" +
            "  :alcoholic: false\n" +
            "  :details: \"\"[Fair Trade Certified]\"\"\n" +
            "  :gluten_free: false\n" +
            "  :kosher: false\n" +
            "  :low_fat: false\n" +
            "  :organic: false\n" +
            "  :sugar_free: false\n" +
            "  :fat_free: false\n" +
            "  :vegan: false\n" +
            "  :vegetarian: false\n" +
            "\",,2015-11-01 00:06:19.796944"

    String suspectString = "---\n" +
            "product_attributes:\n" +
            "-\n" +
            "- :name: Ornaments\n" +
            "  :brand_id: 49120\n" +
            "  :size: each\n" +
            "  :alcoholic: false\n" +
            "  :details: \"[Fair Trade Certified]\"\n" +
            "  :gluten_free: false\n" +
            "  :kosher: false\n" +
            "  :low_fat: false\n" +
            "  :organic: false\n" +
            "  :sugar_free: false\n" +
            "  :fat_free: false\n" +
            "  :vegan: false\n" +
            "  :vegetarian: false\n"

    when:
    String[] values = parser.parseLine(bigline)

    then:
    values.length == 5
    values[0] == "28613099"
    values[1] == "Product::Source"
    values[2] == suspectString
}
 类似资料:
  • 问题内容: 即使已转义,双引号也会引发解析错误。 看下面的代码 由于双引号(已被转义),因此将引发解析错误。 甚至在这里都不行。 但是,如果我用这样的双斜杠将其转义: 然后就可以了 为什么我们需要在javascript中使用双斜杠?问题是,PHP 函数转义一个单斜杠双引号(是这样的:),这将无法解析。我该如何处理这种情况? 问题答案: 好吧,最后,JSON的解析使用相同的eval,因此,给它们sm

  • 我正在使用opencsv读取csv文件。有时csv文件中包含单引号或双引号。如何读取它们而不更改csv文件本身中的数据。 现在,如果我用两个单引号替换一个单引号,它工作正常,与双引号相同,用两个替换单个引号,它的工作原理。但我不想碰源文件。 要访问的代码如下: 这样做的结果是跳过下一行(也包含双引号),插入所有奇数行,跳过偶数行 提前谢谢

  • 这里,整个“service.getdata”语句应该是一个匹配项,但它在(转义的)双引号处中断。如果我用双引号括起参数值,它就可以工作了(就像它在前面的示例块中所做的那样)。但不幸的是,当参数值没有用双引号包装时,我需要它也能工作。 有人能帮我做最后一块吗?

  • 我正在尝试使用opencsv(3.10版)解析一些公共数据。以下是获取CSV并将记录映射到POJO列表的代码片段: 解析列表中的记录比CSV中的少。查看数据,我注意到单元格值中有时会有双引号。这是一个例子: “36”以下的组块导致后续记录与描述一致。通过IDE查看时,这一点更为明显: 你能看出我做错了什么吗?我怀疑有一个简单的解决方案,因为Excel正确解析了它,而opencsv似乎是Java C

  • 问题内容: 我有此命令可以执行我想要的操作,但无法在我的.bashrc中使用别名(请注意,它同时使用单引号和双引号): 我试过了: 还有一些其他没有运气的常识组合。.我知道bash带有引号是非常挑剔的。.因此,为它加上别名的正确方法是什么?为什么?谢谢 问题答案: 您只需要正确地转义即可。

  • 我想打印如下内容: abc、def、ghi、JKL、mno、pqr 我刚写的时候: 所以我试着: 这给了我: abc、def、ghi、jkl、mno、pqr