2017-01-31 2 views
0

Ich versuche, eine CSV-Datei mit OpenCSV zu analysieren. Eine der Spalten speichert die Daten im serialisierten YAML-Format und wird in Anführungszeichen gesetzt, da sie ein Komma enthalten kann. Es enthält auch Anführungszeichen, so dass es durch das Setzen von zwei Anführungszeichen gematcht wird. Ich bin in der Lage, diese Datei in Ruby leicht zu analysieren, aber mit OpenCSV kann ich es nicht vollständig analysieren. Es ist eine UTF-8-kodierte Datei.Parse CSV mit OpenCSV mit doppelten Anführungszeichen in einem Feld in Anführungszeichen

Hier ist mein Java-Schnipsel, die die Datei von dieser Datei

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

Hier sind 2 Zeilen zu lesen versucht. Die erste Zeile wird nicht richtig geparst und wird bei ""[Fair Trade Certified]"" aufgrund von doppelten Anführungszeichen geteilt.

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,,,,,, 
+1

Die "Standard" für CSV-Dateien RFC4180 ist, aber nicht immer folgt. Dazu gehören das Angeben von Feldern mit Kommas und das Umwandeln von inneren Anführungszeichen in zwei Anführungszeichen. Googling "RFC4180 Java Parser" bietet einige Möglichkeiten. – Paul

+0

Mit * OpenCSV * können Sie es nicht analysieren. Kredit, wo Kredit fällig ist. – EJP

+0

@EJP weiß nicht, was Sie damit implizieren :) Aber sowieso, mit einem Parser kompatibel RFC4180 repariert es. – invinc4u

Antwort

2

Die Lösung war eine RFC4180 kompatiblen CSV-Parser zu verwenden, wie https://stackoverflow.com/users/103081/paul vorgeschlagen. Ich hatte den CSVReader von OpenCSV benutzt, der nicht funktionierte oder ich konnte es nicht richtig funktionieren lassen.

I verwendet https://github.com/osiegmar/FastCSV, einen RFC4180 CSV-Parser, und es funktionierte nahtlos.

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()); 
} 
+0

OpenCSV zumindest ab Version 4.1 hat einen RFC4180 Parser. Hier ist das Javadoc: http://opencsv.sourceforge.net/apidocs/com/opencsv/RFC4180Parser.html – dazito

0

Zunächst einmal bin ich froh, dass die FastCSV für Sie gearbeitet, aber ich lief den Verdacht Teilzeichenfolge und lief sie durch die 3,9 openCSV und es funktionierte sowohl mit dem CsvParser und der RFC4180Parser. Könnten Sie bitte ein wenig Details darüber geben, wie es nicht analysiert wurde und/oder es mit 3.9 openCSV versuchen, um zu sehen, ob Sie das gleiche Problem bekommen, und dann versuchen Sie es mit der Konfiguration unten.

Hier sind die Tests, die ich verwendet:

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]); 
} 

RFC4180Parser

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 
} 
Verwandte Themen