Apache Camel处理定长文件:跳过表头返回迭代器而非目标文件问题
解决Apache Camel中使用
skip(3)返回Iterator而非处理后文本的问题 我完全懂你的困扰——本来想跳过前3行表头,结果拿到的却是Iterator对象引用,完全不是预期的处理后文本。这其实是因为Camel的Simple语言中skip(n)的行为和你想的不一样,尤其是当body是字符串的时候。
问题根源
当你把body转成String后调用transform().simple("skip(3)"),Camel会把String当成字符序列来处理:skip(3)会跳过前3个字符,然后返回一个字符迭代器,而不是跳过前3行并返回剩余的文本内容。这就是为什么日志里会出现org.apache.camel.util.SkipIterator@xxx的原因。
正确的解决方案
针对定长文本文件,我们需要先按行分割内容,跳过前3行,再把剩余的行重新拼接成完整文本。这里提供两种可靠的实现方式:
方法1:使用Split + Filter + Aggregate(Camel原生组件)
这种方式利用Camel的路由组件完成处理,不需要写太多自定义代码:
from(inputFilePath).routeId("MyRoute") .streamCaching() .threads(threadPoolSize) .log("${headers.CamelFileName}: Unmarshalling to Java POJO") .log("Body Before Transform: ${body}") // 按换行符分割文本为行的流 .split(body().tokenize("\n")) // 跳过索引小于3的行(SplitIndex从0开始计数) .filter(simple("${exchangeProperty.CamelSplitIndex} >= 3")) // 将剩余的行聚合为完整文本,用换行符连接 .aggregate(constant(true), StringAggregator.DEFAULT) .completionSize(simple("${exchangeProperty.CamelSplitSize} - 3")) .completionTimeout(1000) // 超时兜底,避免无限等待 .log("Body After Transform: ${body}") .to(outputFilePath);
tokenize("\n"):把整个文本按行分割,保留原有的换行格式CamelSplitIndex:Camel提供的分割索引属性,从0开始,所以>=3就是跳过前3行StringAggregator.DEFAULT:默认的聚合器,用换行符把行重新拼接起来,保证输出格式和原文件一致
方法2:自定义Processor(更灵活,适合复杂场景)
如果你的定长文件有特殊格式要求(比如末尾空行需要保留),自定义Processor会更直观可控:
from(inputFilePath).routeId("MyRoute") .streamCaching() .threads(threadPoolSize) .log("${headers.CamelFileName}: Unmarshalling to Java POJO") .log("Body Before Transform: ${body}") .convertBodyTo(String.class) .process(exchange -> { String content = exchange.getIn().getBody(String.class); // 按换行分割,-1参数保留末尾的空行(避免破坏定长格式) String[] lines = content.split("\n", -1); StringBuilder processedContent = new StringBuilder(); // 从第4行开始(索引3)遍历 for (int i = 3; i < lines.length; i++) { processedContent.append(lines[i]); // 除了最后一行,都添加换行符 if (i != lines.length - 1) { processedContent.append("\n"); } } exchange.getIn().setBody(processedContent.toString()); }) .log("Body After Transform: ${body}") .to(outputFilePath);
split("\n", -1):这个参数很重要,能保留文本末尾的空行,确保定长文件的结构不被破坏- 手动拼接行:完全控制每一行的处理逻辑,适合需要额外行处理的场景
关键注意事项
- 不要直接在String类型的body上使用
skip(3):它会迭代字符而非行,完全达不到跳过表头的目的 - 保留定长格式:处理时要注意保留原有的换行符和空行,避免输出文件长度和格式不符合要求
- 流缓存:因为使用了
streamCaching(),确保大文件处理时不会内存溢出
内容的提问来源于stack exchange,提问作者Urn
相关产品推荐
相关产品推荐

