2014-08-30 77 views
2

我有由多行組成的第二值的一一行CSV:Apache的駱駝:解析與多線CSV文件值

field1,"this 

is still 

field2","field3" 

我想使用Apache的駱駝就搞定了,它就像一個JSON這個(解析文件後):

{"field1":"field1","field2":"this 

is still 

field2","field3":"field3"} 

但使用如下代碼:

from('something...') 
    .transform(simple('/path/demooneline.csv', File.class)) 
     .unmarshal().bindy(BindyType.Csv, Demo.class) 
     .marshal().json(JsonLibrary.Jackson).log('${body}') 

@CsvRecord(separator = ',') 
class Demo { 

    @JsonView 
    @DataField(pos = 1) 
    private String field1 

    @JsonView 
    @DataField(pos = 2) 
    private String field2 

    @JsonView 
    @DataField(pos = 3) 
    private String field3 

} 

我GETT掀背:

{"field1":"field1","field2":"this","field3":null}, 
{"field1":"is still","field2":null,"field3":null}, 
{"field1":null,"field2":"field3","field3":null} 

,它看起來像在3行分離的CSV,而不是與由引號分隔一些字段1行。默認情況下@CsvRecord有「quote」。有沒有辦法解析這種類型的CSV與駱駝(使用或不綁定)?

回答

3

問題是您的CSV文件不是「典型的」。來自Wikipidia

「CSV」不是一個明確定義的單一格式(儘管常見的定義見RFC 4180)。更確切地,在實踐中,術語「CSV」是指任何文件:

  1. 使用字符純文本設置諸如ASCII,Unicode的,EBCDIC,或Shift JIS,
  2. 由記錄(通常爲一個每行記錄)
  3. 與分成由分隔符分隔的字段中的記錄(通常是單個保留字符諸如逗號,分號或標籤;有時定界符可以包括可選的空格),
  4. 其中每個記錄具有相同的字段序列。

在你的情況,你的記錄跨越多行,這就是爲什麼駱駝如您所願,駱駝是假設每一行都是不同的唱片不解析它。

編輯

正如我在評論中提到,它看起來像駱駝Bindy不處理包含換行符引述領域。作爲解決方法,您可以「預處理」源CSV文件以替換qoutes內的換行符。例如,使用Guava

from("file:///csvSrcDir?noop=true") 
     .process(new Processor() { 
      @Override 
      public void process(Exchange exchange) throws Exception { 
      final String inBody = exchange.getIn().getBody(String.class); 
      final Iterable<String> tokens = Splitter.on("\",").split(inBody); 
      final Iterable<String> fixedTokens = FluentIterable.from(tokens).transform(new Function<String, String>() { 
       @Nullable 
       @Override 
       public String apply(String input) { 
       return input.contains("\"\n") ? input : input.replace("\n", "<br>"); 
       } 
      }); 
      final String outBody = Joiner.on("\",").join(fixedTokens); 
      exchange.getOut().setBody(outBody); 
      } 
     }) 
     .unmarshal().bindy(BindyType.Csv, Demo.class) 
     .split(body()) 
     .process(new Processor() { 
      @Override 
      public void process(Exchange exchange) throws Exception { 
      Demo body = exchange.getIn().getBody(Demo.class); 
      } 
     }); 

定製處理器將這個CSV文件:

"record 1 field1","this 

is still 

record 1 field2","record 1 field3" 
"record 2 field1","this 

is still 

record line 2 field2","record 2 field3" 

文件分爲:

"record 1 field1","this<br><br>is still<br><br> record 1 field2","record 1 field3" 
"record 2 field1","this<br><br>is still<br><br> record 2 field2","record 2 field3" 

其中Bindy可以處理。

+0

在你發佈的鏈接中寫道:走向標準化:應該引用包含換行符,雙引號和/或逗號的字段。 (如果它們不是,那麼該文件可能無法正確處理),如我的示例。 – Randomize 2014-08-31 05:51:07

+0

是的,但據我所知,通過查看'Camel-2.13.2'中的'BindyCsvDataFormat'的源代碼,它不處理包含換行符的引用字段。 – 2014-08-31 06:44:49

+0

有趣的是,在@CsvRecord源文件中有一個名爲'quote'的字段,我認爲它是指這個問題。 – Randomize 2014-08-31 07:52:10