2014-08-30 78 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