Univocity — неправильный разбор csv

У меня есть нерегулярные (хотя и непротиворечивые) файлы "csv", которые мне нужно проанализировать. Контент выглядит так:

Field1: Field1Text
Field2: Field2Text

Field3 (need to ignore)
Field4 (need to ignore)

Field5
Field5Text

// Cars - for example
#,Col1,Col2,Col3,Col4,Col5,Col6
#1,Col1Text,Col2Text,Col3Text,Col4Text,Col5Text,Col6Text
#2,Col1Text,Col2Text,Col3Text,Col4Text,Col5Text,Col6Text
#3,Col1Text,Col2Text,Col3Text,Col4Text,Col5Text,Col6Text

В идеале я хотел бы использовать подход, аналогичный здесь.

В конечном итоге я хочу получить такой объект, как:

String field1;
String field2;
String field5;
List<Car> cars;

В настоящее время у меня есть следующие проблемы:

  • После добавления некоторых исследовательских тестов строки, начинающиеся с решетки (#), игнорируются. Я не хочу этого, есть ли способ сбежать?
  • Я намеревался использовать BeanListProcessor для раздела cars и обрабатывать другие поля, используя отдельные процессоры строк. Затем объедините результат в объект, упомянутый выше. Я пропустил какие-либо трюки здесь?

person Hurricane    schedule 06.07.2017    source источник


Ответы (1)


Ваша первая проблема связана с #, который по умолчанию рассматривается как символ комментария. Чтобы строки, начинающиеся с #, не воспринимались как комментарий, сделайте следующее:

parserSettings.getFormat().setComment('\0');

Что касается структуры, которую вы анализируете, нет способа сделать это из коробки, но для этого легко использовать API. Будет работать следующее:

    CsvParserSettings settings = new CsvParserSettings();
    settings.getFormat().setComment('\0'); //prevent lines starting with # to be parsed as comments

    //Creates a parser
    CsvParser parser = new CsvParser(settings);

    //Open the input
    parser.beginParsing(new File("/path/to/input.csv"), "UTF-8");

    //create BeanListProcessor for instances of Car, and initialize it.
    BeanListProcessor<Car> carProcessor = new BeanListProcessor<Car>(Car.class);
    carProcessor.processStarted(parser.getContext());

    String[] row;
    Parent parent = null;
    while ((row = parser.parseNext()) != null) { //read rows one by one.
        if (row[0].startsWith("Field1:")) {  // when Field1 is found, create your parent instance
            if (parent != null) { //if you already have a parent instance, cars have been read. Associate the list of cars to the instance
                parent.cars = new ArrayList<Car>(carProcessor.getBeans()); //copy the list of cars from the processor.
                carProcessor.getBeans().clear(); //clears the processor list
                //you probably want to do something with your parent bean here.
            }
            parent = new Parent(); //create a fresh parent instance
            parent.field1 = row[0]; //assign the fields as appropriate.
        } else if (row[0].startsWith("Field2:")) {
            parent.field2 = row[0]; //and so on
        } else if (row[0].startsWith("Field5:")) {
            parent.field5 = row[0];
        } else if (row[0].startsWith("#")){ //got a "Car" row, invoke the rowProcessed method of the carProcessor.
            carProcessor.rowProcessed(row, parser.getContext());
        }
    }

    //at the end, if there is a parent, get the cars parsed
    if (parent != null) {
        parent.cars = carProcessor.getBeans();
    }

Чтобы BeanListProcessor работал, вам нужно объявить свой экземпляр следующим образом:

public static final class Car {
    @Parsed(index = 0)
    String id;
    @Parsed(index = 1)
    String col1;
    @Parsed(index = 2)
    String col2;
    @Parsed(index = 3)
    String col3;
    @Parsed(index = 4)
    String col4;
    @Parsed(index = 5)
    String col5;
    @Parsed(index = 6)
    String col6;
}

Вместо этого вы можете использовать заголовки, но это заставит вас писать больше кода. Если заголовки всегда одинаковы, вы можете просто предположить, что позиции фиксированы.

Надеюсь это поможет

person Jeronimo Backes    schedule 09.07.2017
comment
Спасибо, что нашли время ответить Джеронимо. Также очень нравится пользоваться парсерами! - person Hurricane; 25.07.2017