我编写了一个简单的路线来读取 CSV 文件并将其保存在 JSON 格式的新文件中。
当我尝试拆分和流式传输正文时,解组会因“.IllegalArgumentException:CSV 中没有定义记录”而中断。
但是,无需拆分和流式传输,它也能正常工作!
Unmarshal 使用 BindyCsvDataFormat 和 CustomCsvRecord 定义字段。
CSV Sample:
HEADER_1;HEADER_2;HEADER_3;HEADER_4;HEADER_5
data11;data12;data13;data14;data15
data21;data22;data23;data24;data25
您能帮助我了解这是正确的行为吗?如果是,我如何控制读取大文件?
请参考以下:
public class MyRouteBuilder extends RouteBuilder {
public void configure() {
BindyCsvDataFormat bindy = new BindyCsvDataFormat(com.demo.camel.CustomCsvRecord.class);
from("file://data?move=../completed/&include=.*.csv&charset=UTF-8")
.log("Reading file..")
// .split(body().tokenize("\n")).streaming()
// .throttle(2)
// .timePeriodMillis(3000)
.unmarshal(bindy)
.marshal().json(true)
.log("writing to file")
.to("file://target/messages?fileExist=Append");
}
}
@CsvRecord(separator = ";", skipFirstLine = true )
public class CustomCsvRecord implements Serializable{
private static final long serialVersionUID = -1537445879742479656L;
@DataField(pos = 1)
private String header_1;
@DataField(pos = 2)
private String header_2;
@DataField(pos = 3)
private String header_3;
@DataField(pos = 4)
private String header_4;
@DataField(pos = 5)
private String header_5;
public String getHeader_1() {
return header_1;
}
public void setHeader_1(String header_1) {
this.header_1 = header_1;
}
public String getHeader_2() {
return header_2;
}
public void setHeader_2(String header_2) {
this.header_2 = header_2;
}
public String getHeader_3() {
return header_3;
}
public void setHeader_3(String header_3) {
this.header_3 = header_3;
}
public String getHeader_4() {
return header_4;
}
public void setHeader_4(String header_4) {
this.header_4 = header_4;
}
public String getHeader_5() {
return header_5;
}
public void setHeader_5(String header_5) {
this.header_5 = header_5;
}
}
难道你设置了skipFirstLine = true?但由于您使用换行符进行分割,因此跳过第一行意味着没有行可以解析 CSV。试试这个吧
.split().tokenize("\n", 1000).streaming()
。这基本上意味着我们要根据代币进行拆分”
“并且我们想要将 N 行组合在一起。在本例中,它是 1000,因此最多会将 1000 行组合在一起。
因此,如果您发送 10 000 行,它会将它们分成 10 个块。
现在的问题是,如果您设置了skipFirstLine,它将跳过第一行。由于您之前分割了每一行,因此当涉及 CSV 解析器时,它会跳过该行,因为这是它被告知要执行的操作。因此,没有什么可解析的,它抱怨没有记录。
现在的问题是,每 1000 行进行一次分割后会发生什么,得到 10000 行。它会删除每个分割块中的第一行吗?我怀疑是这样。我认为最好的办法是在拆分之前添加一个处理器。将正文转换为 byte[]。搜索第一个“ " 并简单地删除该行或获取该索引之后的 byteArray。然后您可以进行正常拆分并删除skipFirstRow。
此外,您的输出位于列表中,但这是由于您的映射所致。
如果您想跳过 CSV 的第一行,这只是一个快速提示,可以让事情变得更容易。 .tokenize() 方法中有一个方便的功能,您可以使用一个简单的标志告诉 Camel 忽略第一行。看起来像这样:
.split().tokenize("\n", 1000, true).streaming()
通过将最后一个参数设置为 true,Camel 巧妙地跳过第一个换行符,使标题不被分割。这意味着您的
skipFirstLine = true
中不再需要 @CsvRecord
,因此请继续将其设置为 false 或将其删除。这样,当您将文件分成一千行的块时,它不会跳过每个块的第一行 - 只会跳过文件开头的标题。
这里是 Camel's(4.4.x) 的文档 tokenize-language