【问题标题】:Apache Camel: Process file line by lineApache Camel:逐行处理文件
【发布时间】:2021-05-04 18:33:29
【问题描述】:

我有一个要读取和处理的大文件。我不想将它完全加载到内存中,而是单独读取文件的每一行并对其执行操作。我在工作期间来到了这个实现:

@Override
public void configure() {
    from(fileSftpLocationUrl)
        .routeId("my-route")
        .onException(Exception.class).handled(true).bean(exchangeErrorHandler, "processError").end()
        .split(body().tokenize("\n")).streaming()
        .filter(/*condition for skip first and last line*/)
        .bean(/*my action*/)
        .to(String.format("activemq:%s", myQueue));
}

在开始读取文件之前,我跳过了页眉和页脚.filter(/*condition for skip first and last line*/),在下一行我尝试开始逐行读取我的文件.split(body().tokenize("\n")).streaming(),但是出了点问题,我从文件中获取了所有信息完整的。在解析该数据并对它们执行操作时,我在 .bean(/*my action*/) 中看到了这个问题。

我认为我的问题在一开始就被隐藏了,因为算法看起来很奇怪,首先我描述了整个文件的条件(跳过页眉和页脚),然后我让 Camel 逐行处理,然后才特定行的操作。

我的问题是,如何更改此实现以便逐行处理文件?

【问题讨论】:

  • 在 Windows 中,行分隔符是 \r\n,在 linux 中是 \n。这会是个问题吗?您可以改用System.lineSeparator() 使其独立于操作系统。
  • 文件是 CSV 吗?
  • 你不需要过滤 AFTER (而不是之前)将它们分成 n 个单独的 msg 的行吗?先拆分,再过滤
  • > 你好@pratap。谢谢你的评论。分隔符没问题。我确定这不是重点。 > 你好@BSangappa。不,它是。这是一个简单的.txt 文件,但看起来像.csv,内容由| 符号分隔成列。 > 你好@TacheDeChoco。是的,对不起。我的错。复制粘贴代码时出错。在我的实现中,我在拆分后进行填充。我在帖子中修复了代码。

标签: java apache-camel spring-camel camel-ftp


【解决方案1】:

我想我明白了。 默认情况下,拆分结果发送到FIRST下一个端点

from(...)
    .split(body().tokenize("\n")).streaming()
    .to("direct:processLine")

如果要发送到复杂的路由,则必须标记拆分结尾,例如

from(...)
       
     .split(body().tokenize("\n")).streaming()
        .filter(/*condition for skip first and last line*/)
        .bean(/*my action*/)
        .to(String.format("activemq:%s", myQueue))
     .end()
     .log("Split done");

如果省略 end(),则逻辑如下(见缩进):

from(...)
       
     .split(body().tokenize("\n")).streaming()
        .filter(/*condition for skip first and last line*/)
     .end() // Implicit 
     .bean(/*my action*/)
     .to(String.format("activemq:%s", myQueue))         

-> 在您的尝试中,使用原始消息调用了 bean(...)(在执行拆分之后)

将其视为一种“for-loop”

for (String line: lines) 
filter(line);
bean.run(line);
sendto(...);

根本不一样:

for (String line: lines) {
  filter(line);
  bean.run();
  sendto(...);
}

【讨论】:

  • 谢谢,@TacheDeChoco 我认为最后一个变体是我的,因为当我们end() 特定文件操作以及之后我们对文件行执行特定操作时,它看起来合乎逻辑。但它打破了我的过滤器:pastebin.pl/view/raw/b07c83bf
  • 您必须将带有bean(...) 的变体拆分,以便将过滤后的拆分项发送到bean。 pastebin.pl/view/d298ff2d
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-28
  • 1970-01-01
  • 1970-01-01
  • 2021-01-28
  • 1970-01-01
相关资源
最近更新 更多