2016-09-15 1 views
2

CSV 파일을 읽고 JSON 형식의 새 파일로 저장하는 간단한 경로를 작성했습니다. Apache Camel 2.17.3 - 바인딩으로 CSV 스트림을 언 마샬링하는 예외적 인 경우

I 분할과 몸을 가진 비 정렬 화 휴식 스트리밍하려고

".IllegalArgumentException을 : 없음 레코드가 CSV에 정의되지 않았습니다."

그러나 분할 및 스트리밍없이 원활하게 작동합니다.

비 정렬 화는 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; 
    } 
} 
+1

그리고 구분 기호가 \ n이지 CRLF가 아니라고 확신합니다 \ r \ n? –

+0

예, 위의 예제 본문은 "\ n"을 사용하여 분할되지만 "\ r \ n"인 경우에도 동일한 결과가 생성됩니다. 나는 언 마샬링하지 않고 스트림을 보내고 "\ n"을 사용하여 조절할 수 있습니다. – Vinay

+0

샘플 CSV를 5 행으로 보내고 스플릿 및 스트림 후에 본문을 기록하면 본문은 어떻게 생겼습니까? –

답변

2

는 당신이 skipFirstLine = true를 설정했는지 될 수 있을까? 그러나 줄 바꿈을 사용하여 분할 했으므로 첫 줄을 건너 뛰면 CSV를 구문 분석 할 줄이 없음을 의미합니다. 대신 .split().tokenize("\n", 1000).streaming()을 사용해보세요. 이것은 기본적으로 우리가 토큰 "\ n"을 기반으로 분할하려는 것을 의미하며 우리는 N 개의 라인을 함께 그룹화하려고합니다. 이 경우에는 1000이므로 대부분의 그룹에서 1000 줄을 함께 나누게됩니다.

그래서 10 000 개의 행을 보내면 10 개의 덩어리로 나뉩니다. 당신이 skipFirstLine 그것이 첫 번째 줄을 건너 뜁니다 설정 한 경우

지금 문제입니다. 이전에 각 줄을 나누었으므로 CSV 파서가 왔을 때 그 줄을 건너 뛸 것입니다. 따라서 해석 할 내용이 없으며 기록이 없다고 불평합니다.

문제는 이제 1000 개 행마다 말하고 10,000 개 행을 나누면 어떻게 될지 문제가 있습니다. 모든 분할 된 덩어리에서 첫 번째 줄이 제거됩니까? 나는 그렇게 의심 할 것이다. 가장 좋은 방법은 분할 전에 프로세서를 추가하는 것입니다. 본문을 byte []로 변환하십시오. 첫 번째 "\ n"을 검색하고 해당 행을 삭제하거나 해당 인덱스 다음에 byteArray를 가져옵니다. 그런 다음 정상적인 분할을 수행하고 skipFirstRow를 제거 할 수 있습니다.

또한 출력이 목록에 있지만 매핑 때문입니다.

관련 문제