2016-09-15 5 views
2

Я написал простой маршрут для чтения CSV-файла и сохранения его в новом файле в формате JSON.Apache Camel 2.17.3 - Исключение unmarshalling CSV-потока с bindy

Когда я пытаюсь расколоть и течь тело, немаршал разбивается на «.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; 
    } 
} 
+1

И вы уверены, что ваш разделитель \ n, а не CRLF \ r \ n? –

+0

да, приведенное выше тело тела разбивается с помощью «\ n», однако даже с «\ r \ n» получается тот же результат. Я могу передать его без unmarshalling и отлично работает с дросселированием, используя «\ n» – Vinay

+0

Если вы отправляете образец CSV, скажем 5 строк, и регистрируете тело после разделения и потока, как выглядит тело? –

ответ

2

Может быть, что вы установили skipFirstLine = верно? Но так как вы разделились с разрывом строки, пропуская первую строку, значит нет линий для разбора CSV. Попробуйте это вместо .split().tokenize("\n", 1000).streaming(). Это в основном означает, что мы хотим разбить на основе токена «\ n», и мы хотим сгруппировать N количество строк вместе. В этом случае он равен 1000, поэтому он будет в максимальной группе 1000 строк вместе в расколе.

Так что если вы отправляете 10 000 строк, он разделит их на 10 кусков.

Теперь проблема в том, что если у вас установлен skipFirstLine, он пропустит первую строку. Поскольку вы ранее разделяли каждую строку, когда дело дошло до анализатора CSV, он пропустил эту строку, так как это было сказано. Итак, тогда нет ничего, чтобы разобрать, и он жаловался, что нет записей.

Проблема теперь в том, что происходит после того, как вы разделите, скажем, каждые 1000 строк, и вы получите 10 000 строк. Удалит ли он первую строку в каждом фрагменте? Я бы так заподозрил. Я бы подумал, что лучше всего добавить процессор перед расколом. Преобразуйте тело в байт []. Найдите первый «\ n» и просто удалите эту строку или получите byteArray после этого индекса. Затем вы можете выполнить обычный сплит и удалить skipFirstRow.

Кроме того, ваш вывод находится в списке, но это связано с вашим отображением.