Apache camel 在Apache Camel中处理大型CSV文件的最佳策略

Apache camel 在Apache Camel中处理大型CSV文件的最佳策略,apache-camel,Apache Camel,我想开发一个路由,轮询包含CSV文件的目录,并使用Bindy为每个文件解组每一行,并在activemq中对其进行排队 问题是文件可能非常大(一百万行),所以我更愿意一次排队一行,但我得到的是Bindy末尾java.util.ArrayList中的所有行,这会导致内存问题 到目前为止,我有一个小测试,解组工作正常,所以使用注释的Bindy配置是可以的 路线如下: from("file://data/inbox?noop=true&maxMessagesPerPoll=1&delay

我想开发一个路由,轮询包含CSV文件的目录,并使用Bindy为每个文件解组每一行,并在activemq中对其进行排队

问题是文件可能非常大(一百万行),所以我更愿意一次排队一行,但我得到的是Bindy末尾java.util.ArrayList中的所有行,这会导致内存问题

到目前为止,我有一个小测试,解组工作正常,所以使用注释的Bindy配置是可以的

路线如下:

from("file://data/inbox?noop=true&maxMessagesPerPoll=1&delay=5000")
  .unmarshal()
  .bindy(BindyType.Csv, "com.ess.myapp.core")           
  .to("jms:rawTraffic");
环境是:EclipseIndigo、Maven 3.0.3、Camel 2.8.0


谢谢

如果您使用拆分器EIP,那么您可以使用流模式,这意味着Camel将逐行处理文件

from("file://data/inbox?noop=true&maxMessagesPerPoll=1&delay=5000")
  .split(body().tokenize("\n")).streaming()
    .unmarshal().bindy(BindyType.Csv, "com.ess.myapp.core")           
    .to("jms:rawTraffic");

对于记录和其他可能像我一样搜索此内容的用户,同时似乎有一种更简单的方法也适用于:


使用拆分器和聚合器EIP将是在Apache Camel中处理大型CSV文件的最佳策略。从表格中了解更多信息

下面是一个使用Java DSL的示例:

package com.camel;

import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.dataformat.csv.CsvDataFormat;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.QuoteMode;

public class FileSplitter {

    public static void main(String args[]) throws Exception {
        CamelContext context = new DefaultCamelContext();
        CsvDataFormat csvParser = new CsvDataFormat(CSVFormat.DEFAULT);
        csvParser.setSkipHeaderRecord(true);
        csvParser.setQuoteMode(QuoteMode.ALL);
        context.addRoutes(new RouteBuilder() {
            public void configure() {
                String fileName = "Hello.csv";
                int lineCount = 20;
                System.out.println("fileName = " + fileName);
                System.out.println("lineCount = " + lineCount);
                from("file:data/inbox?noop=true&fileName=" + fileName).unmarshal(csvParser).split(body()).streaming()
                        .aggregate(constant(true), new ArrayListAggregationStrategy()).completionSize(lineCount)
                        .completionTimeout(1500).marshal(csvParser)
                        .to("file:data/outbox?fileName=${file:name.noext}_${header.CamelSplitIndex}.csv");
            }
        });
        context.start();
        Thread.sleep(10000);
        context.stop();
        System.out.println("End");
    }
}

谢谢克劳斯的回答。现在我面临一个不同的问题。在我的小练习之后,我试图从队列中提取并使用
.convertBodyTo(String.class).to(“file:data/outbox?fileExist=Append”)
写入文件,但只写入第一行。同样,如果我使用file选项Override,我只会得到最后一行。是否有办法将CSV文件中的所有行写入该文件?。谢谢您需要指定文件名,.to(“file:data/outbox?fileName=data.csv&fileExist=Append”)在
之后添加
.thread()
。streaming()
是否更高效?拆分器EIP内置多线程支持,您可以参考Executor服务。使用它比使用线程更理想。但后者也是可能的。参见Camel文档中的示例。我看到通过新行标记化。多行行呢?是否支持该计划?
package com.camel;

import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.dataformat.csv.CsvDataFormat;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.QuoteMode;

public class FileSplitter {

    public static void main(String args[]) throws Exception {
        CamelContext context = new DefaultCamelContext();
        CsvDataFormat csvParser = new CsvDataFormat(CSVFormat.DEFAULT);
        csvParser.setSkipHeaderRecord(true);
        csvParser.setQuoteMode(QuoteMode.ALL);
        context.addRoutes(new RouteBuilder() {
            public void configure() {
                String fileName = "Hello.csv";
                int lineCount = 20;
                System.out.println("fileName = " + fileName);
                System.out.println("lineCount = " + lineCount);
                from("file:data/inbox?noop=true&fileName=" + fileName).unmarshal(csvParser).split(body()).streaming()
                        .aggregate(constant(true), new ArrayListAggregationStrategy()).completionSize(lineCount)
                        .completionTimeout(1500).marshal(csvParser)
                        .to("file:data/outbox?fileName=${file:name.noext}_${header.CamelSplitIndex}.csv");
            }
        });
        context.start();
        Thread.sleep(10000);
        context.stop();
        System.out.println("End");
    }
}