Camel bindy маршалирует в файл, создает несколько строк заголовка

У меня есть следующий маршрут верблюда:

from(inputDirectory)
  .unmarshal(jaxb)
  .process(jaxb2CSVDataProcessor)
  .split(body()) //because there is a list of CSVRecords
  .marshal(bindyCsvDataFormat)
  .to(outputDirectory); //appending to existing file using "?autoCreate=true&fileExist=Append"

для моего класса модели CSV я использую аннотации:

@CsvRecord(separator = ",", generateHeaderColumns = true)
...

и для свойств

@DataField(pos = 0)
...

Моя проблема в том, что заголовки добавляются каждый раз, когда добавляется новая запись csv.

Есть ли не грязный способ контролировать это? Я что-то пропустил здесь?


person theo    schedule 14.12.2016    source источник
comment
добавляются ли заголовки для каждой записи или для каждого потребляемого файла?   -  person dimitrisli    schedule 15.12.2016
comment
Для каждой записи.   -  person theo    schedule 15.12.2016
comment
Это ожидаемо, потому что вы вызываете маршала в сплиттере. Попробуй без разветвителя.   -  person Claus Ibsen    schedule 15.12.2016
comment
Ну, я должен использовать сплиттер, так как каждый входной файл будет создавать несколько записей CSV, я боюсь.   -  person theo    schedule 15.12.2016
comment
@ClausIbsen, вы были правы, bindy обработает список CsvRecords, когда я удалю сплиттер. Однако проблема все еще остается. Поскольку я добавляю к одному и тому же файлу (до конечной точки), каждый раз, когда ввод файла (из конечной точки) bindy заканчивается воссозданием заголовков.   -  person theo    schedule 16.12.2016
comment
Затем вам нужно пропустить первую строку, если файл существует, вам нужно будет добавить некоторую логику, чтобы понять это.   -  person Claus Ibsen    schedule 16.12.2016


Ответы (3)


Я сделал работу, которая работает довольно хорошо, создав заголовок, запросив имена столбцов аннотации @DataField. Это происходит при первой записи файла. Я записал все решение здесь:

Как создать плоский файл с верхним и нижним колонтитулом с помощью Camel Bindy

person Viktor Stoitschev    schedule 20.03.2019

В итоге я добавил процессор, который проверяет, существует ли файл csv непосредственно перед предложением «to». Там я манипулирую массивом байтов и удаляю заголовки.

person theo    schedule 16.12.2016

Надеюсь, это поможет кому-то еще. Мне нужно было сделать что-то подобное, когда после моего первого разделенного сообщения я хотел подавить вывод заголовка. Вот полный класс («FieldUtils» является частью библиотеки Apache Commons)

package com.routes;

import java.io.OutputStream;

import org.apache.camel.Exchange;
import org.apache.camel.dataformat.bindy.BindyAbstractFactory;
import org.apache.camel.dataformat.bindy.BindyCsvFactory;
import org.apache.camel.dataformat.bindy.BindyFactory;
import org.apache.camel.dataformat.bindy.FormatFactory;
import org.apache.camel.dataformat.bindy.csv.BindyCsvDataFormat;
import org.apache.commons.lang3.reflect.FieldUtils;

public class StreamingBindyCsvDataFormat extends BindyCsvDataFormat {

    public StreamingBindyCsvDataFormat(Class<?> type) {
        super(type);
    }

    @Override
    public void marshal(Exchange exchange, Object body, OutputStream outputStream) throws Exception {
        final StreamingBindyModelFactory factory = (StreamingBindyModelFactory) super.getFactory();
        final int splitIndex = exchange.getProperty(Exchange.SPLIT_INDEX, -1, int.class);
        final boolean splitComplete = exchange.getProperty(Exchange.SPLIT_COMPLETE, false, boolean.class);

        super.marshal(exchange, body, outputStream);

        if (splitIndex == 0) {
        factory.setGenerateHeaderColumnNames(false); // turn off header generate after first exchange
        } else if(splitComplete) {
        factory.setGenerateHeaderColumnNames(true); // turn on header generate when split complete
        }
    }

    @Override
    protected BindyAbstractFactory createModelFactory(FormatFactory formatFactory) throws Exception {
        BindyCsvFactory bindyCsvFactory = new StreamingBindyModelFactory(getClassType());
        bindyCsvFactory.setFormatFactory(formatFactory);
        return bindyCsvFactory;
    }

    public class StreamingBindyModelFactory extends BindyCsvFactory implements BindyFactory {

        public StreamingBindyModelFactory(Class<?> type) throws Exception {
            super(type);
        }

        public void setGenerateHeaderColumnNames(boolean generateHeaderColumnNames) throws IllegalAccessException {
            FieldUtils.writeField(this, "generateHeaderColumnNames", generateHeaderColumnNames, true);
        }

    }

}
person Stephen Lawson    schedule 27.05.2021