Разбор строк в SuperCSV

@ Карло В. Данго Я упростил свой вопрос и прочитал документацию - хороший совет не паниковать. Тем не менее, у меня есть проблемы. Помогите мне решить одну, и она решит их все. Спасибо.

Вопрос: Если у меня есть запись csv, в которой отсутствует поле, отличное от строки, как (или даже могу ли я) преобразовать отсутствующую запись в значение по умолчанию или, по крайней мере, не вызывать исключение NullPointerException? Необязательный cellProcessor также не предотвращает ошибку.

Эта программа взята по сути с сайта SuperCSV.

package com.test.csv;
import java.io.FileReader;

import org.supercsv.cellprocessor.ParseBigDecimal;
import org.supercsv.cellprocessor.ParseDate;
import org.supercsv.cellprocessor.ParseInt;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.io.CsvBeanReader;
import org.supercsv.io.ICsvBeanReader;
import org.supercsv.prefs.CsvPreference;


public class CSVReader {

private static final CellProcessor[] cellProcessor = new CellProcessor[] {
    null,
    null,
    new ParseInt(),
    new ParseDate("yyyyMMdd"),      
    new ParseBigDecimal()       
};

public static void main (String[] args ) throws Exception {

    CsvPreference pref = new CsvPreference('"', '|', "\n");

    ICsvBeanReader inFile = new CsvBeanReader(new FileReader("C:\\temp\\sapfilePipe.txt"), pref);
    try {
        final String[] header = inFile.getCSVHeader(true);
        User user;
        while ((user = inFile.read(User.class, header, cellProcessor)) != null) {
            System.out.println(user);
        }
    } finally {
        inFile.close();
    }

}

}

вот файл CSV, который я читаю. Обратите внимание, что в первой записи отсутствует поле (возраст).

firstName|lastName|age|hireDate|hourlyRate
A.|Smith|  |20110101|15.50

Мой пользовательский компонент:

package com.test.csv;

import java.math.BigDecimal;
import java.util.Date;

public class User {

private String firstName;
private String lastName;
private int age;
private Date hireDate;
private BigDecimal hourlyRate;
    ...getters/setters...   

Вот ошибка:

Exception in thread "main" java.lang.NullPointerException
    at org.supercsv.io.CsvBeanReader.fillObject(Unknown Source)
    at org.supercsv.io.CsvBeanReader.read(Unknown Source)
    at com.glazers.csv.CSVReader.main(CSVReader.java:31)

Спасибо.


person Davidson    schedule 27.11.2011    source источник


Ответы (2)


Средство чтения списка считывает каждую строку в список строк. Кажется, это то, что вы ищете.

http://super-csv.github.io/super-csv/apidocs/org/supercsv/io/CsvListReader.html

или как показано здесь http://super-csv.github.io/super-csv/examples_reading.html вы можете установить для процессора значение null, если вы не хотите, чтобы выполнялось что-либо конкретное.

person Carlo V. Dango    schedule 28.11.2011
comment
Привет... Если бы у меня был пустой столбец, который нужно преобразовать в BigDecimal, я попробовал new ParseBigDecimal(new StrReplace(, 0)), - person Davidson; 29.11.2011
comment
При создании процессоров ячеек вы строите их изнутри наружу или снаружи внутрь... например... если у меня есть пробел в столбце, который в противном случае был бы количественным значением, как мне связать процессоры для преобразования пробела в 0, тогда используйте ParseBigDecimal? Я начинаю отчаянно пытаться понять то, чего не понимаю. Осознание того, что я могу поместить нуль в массив CellProcessor, было огромным. Я интерпретировал как прочитанное, но не обработанное в примерах веб-сайта, как «полностью игнорируемое». - person Davidson; 29.11.2011
comment
как показано на supercsv.sourceforge.net/codeExamples_general.html снаружи-внутри. Это первый экземпляр с уникальным процессором. Постарайтесь не паниковать и вместо этого сосредоточьтесь на чтении документации. Он назывался «Начало работы», поэтому должен иметь некоторое значение. - person Carlo V. Dango; 02.12.2011

Изменить: обновление для Super CSV 2.0.0-beta-1

Super CSV 2.0.0-beta-1 уже вышла. Он включает в себя множество исправлений ошибок и новых функций (включая поддержку Maven и новое расширение Dozer для сопоставления вложенных свойств и массивов/коллекций).

Также изменился способ обработки пустых ("") столбцов — теперь они читаются как null. Это означает, что поля firstName и lastName в вашем bean-компоненте теперь будут null вместо "", если их нет в CSV-файле.

Процессор Optional() был обновлен, чтобы соответствовать этому, поэтому он по-прежнему будет работать так же.

Мое предложение использовать Token больше не актуально: вместо этого вы должны использовать ConvertNullTo:

new ConvertNullTo(-1, new ParseInt())

Что вам на самом деле нужно, так это Optional CellProcessor, который позволит следующему процессору в цепочке выполняться только в том случае, если столбец не пуст.

Поэтому обновите массив CellProcessor до:

private static final CellProcessor[] cellProcessor = new CellProcessor[] {
    null,
    null,
    new Optional(new ParseInt()),
    new ParseDate("yyyyMMdd"),      
    new ParseBigDecimal()       
};

Таким образом, ParseInt будет выполняться только в том случае, если столбец не пустой (CellProcessors выполняется слева направо), оставляя поле int в bean-компоненте со значением по умолчанию, равным 0.

Если вы хотите установить для поля значение -1, чтобы указать, что значение не было предоставлено, вы можете использовать процессор Token, который заменит любой токен ("в данном случае") на желаемое значение, для любого другого ввода он будет продолжаться к следующему процессору. то есть

new Token("", -1, new ParseInt())

@Carlo V. Dango CsvListReader - очень примитивная реализация (и вы теряете возможность сопоставления с bean-компонентами), поэтому я бы использовал ее только для быстрого и грязного синтаксического анализа.

И я бы рекомендовал использовать null в массиве (при чтении) только для строковых свойств, которые не требуют дальнейшей обработки.

Кстати, я работаю над проектом Super CSV и работаю над предстоящим релизом. Я обязательно улучшу примеры кода на веб-сайте, пока буду этим заниматься;)

person James Bassett    schedule 12.02.2012
comment
Большое спасибо за этот совет. В случае с моим первоначальным вопросом я пошел по пути создания строк всех полей в bean-компоненте и последующего их анализа в моем процессе. Я возьму этот образец и прогоню на нем свои тесты, используя входные файлы, с которыми мне придется работать. Я всегда думал, что мои проблемы были моей собственной неуклюжестью в цепочке процессоров ячеек. Я люблю читателя / писателей бобов. Наша компания переходит на SAP, который имеет много возможностей для чтения/записи файлов CSV для всех пользовательских интерфейсов. SuperCSV сейчас играет важную роль в нашей обработке. - person Davidson; 12.02.2012
comment
@Davidson Приятно слышать, что вы все еще используете Super CSV - это отличный маленький API. Некоторое время он бездействовал, но недавно я присоединился к проекту и надеюсь вдохнуть в него новую жизнь. Если у вас есть какие-либо вопросы или идеи для новых функций, пишите на форумах Super CSV SourceForge — мы будем рады получить от вас известие. Вам повезло, что ваш интерфейс с SAP - CSV, на моей работе он позиционный (первый столбец - 20 символов, второй - 10 символов и т. д.)!! Кстати, если вы найдете это полезным, не могли бы вы проголосовать/выбрать этот ответ? - person James Bassett; 13.02.2012