Пропуск альтернативных строк при чтении файла .tsv

У меня есть файл .tsv, который имеет 39 столбцов, последний, но один столбец содержит данные в виде строки, длина которой превышает 100 000 символов. Теперь происходит, когда я пытаюсь прочитать строку файла 1 имеет заголовки, а затем следуют данные

Что происходит, так это то, что после чтения строки 1 он переходит к строке 3, затем к строке 5, затем к строке 7. Хотя все строки имеют одинаковые данные. Следуя журналу, я получаю

lineNo=3, rowNo=2, customer=503837-100 , last but one cell length=111275
lineNo=5, rowNo=3, customer=503837-100 , last but one cell length=111275
lineNo=7, rowNo=4, customer=503837-100 , last but one cell length=111275
lineNo=9, rowNo=5, customer=503837-100 , last but one cell length=111275
lineNo=11, rowNo=6, customer=503837-100 , last but one cell length=111275
lineNo=13, rowNo=7, customer=503837-100 , last but one cell length=111275
lineNo=15, rowNo=8, customer=503837-100 , last but one cell length=111275
lineNo=17, rowNo=9, customer=503837-100 , last but one cell length=111275
lineNo=19, rowNo=10, customer=503837-100 , last but one cell length=111275

Ниже приведен мой код:

import java.io.FileReader;
import org.supercsv.cellprocessor.Optional;
import org.supercsv.cellprocessor.constraint.NotNull;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.io.CsvBeanReader;
import org.supercsv.io.ICsvBeanReader;
import org.supercsv.prefs.CsvPreference;

public class readWithCsvBeanReader {
    public static void main(String[] args) throws Exception{
        readWithCsvBeanReader();
    }


private static void readWithCsvBeanReader() throws Exception {

    ICsvBeanReader beanReader = null;

    try {

        beanReader = new CsvBeanReader(new FileReader("C:\MAP TSV\abc.tsv"), CsvPreference.TAB_PREFERENCE);
        // the header elements are used to map the values to the bean (names must match)
        final String[] header = beanReader.getHeader(true);
        final CellProcessor[] processors = getProcessors();
        TSVReaderBrandDTO tsvReaderBrandDTO = new TSVReaderBrandDTO();

        int i = 0;
        int last = 0;

        while( (tsvReaderBrandDTO = beanReader.read(TSVReaderBrandDTO.class, header, processors)) != null ) {
            if(null == tsvReaderBrandDTO.getPage_cache()){
                last = 0;
            }
            else{
                last = tsvReaderBrandDTO.getPage_cache().length();
            }
            System.out.println(String.format("lineNo=%s, rowNo=%s, customer=%s , last but one cell length=%s", beanReader.getLineNumber(),
                beanReader.getRowNumber(), tsvReaderBrandDTO.getUnique_ID(), last));
            i++;
        }

        System.out.println("Number of rows : "+i);

    }
    finally {
        if( beanReader != null ) {
            beanReader.close();
        }
    }
}

private static CellProcessor[] getProcessors() {

    final CellProcessor[] processors = new CellProcessor[] { 
         new Optional(), new NotNull(), new NotNull(), new NotNull(), new NotNull(),
         new NotNull(), new NotNull(), new NotNull(), new NotNull(), new NotNull(),
         new NotNull(), new NotNull(), new NotNull(), new NotNull(), new NotNull(),
         new NotNull(), new NotNull(), new NotNull(), new NotNull(), new NotNull(),
         new NotNull(), new NotNull(), new NotNull(), new NotNull(), new NotNull(),
         new NotNull(), new NotNull(), new NotNull(), new NotNull(), new NotNull(),
         new NotNull(), new NotNull(), new NotNull(), new NotNull(), new NotNull(),
         new NotNull(), new NotNull(), new NotNull(), new Optional()};

        return processors;
    }
}

Пожалуйста, дайте мне знать, где я ошибаюсь


person Subhrajyoti Das    schedule 17.01.2014    source источник


Ответы (2)


Я проверил http://supercsv.sourceforge.net/examples_reading.html. Внимательно изучите Пример CSV-файла и Вывод. Не может ли быть так, что ваши строки содержат неэкранированный символ " (двойной апостроф), поэтому синтаксический анализатор считает, что запись данных занимает две физические строки?

Если вы не используете символ двойного апострофа в качестве символа кавычки, вы можете изменить CsvPreference — см. http://supercsv.sourceforge.net/apidocs/org/supercsv/prefs/CsvPreference.html, чтобы двойная кавычка не считалась кавычкой:

CsvPreference MY_PREFERENCES = new CsvPreference.Builder(
    SOME_NEVER_USED_CHARACTER, ',', "\r\n").build();

Конечно, для CSV с разделителями табуляции используйте что-то вроде этого:

CsvPreference MY_PREFERENCES = new CsvPreference.Builder(
    SOME_NEVER_USED_CHARACTER, '\t', "\r\n").build();

Обратитесь к CsvPreference javadoc для подписи Builder и соответствующим образом измените фактические значения.

person Honza Zidek    schedule 17.01.2014
comment
Ya Honza, вы правы, у него нет экранирования ... можете ли вы предложить какой-либо способ справиться с этим во время выполнения? - person Subhrajyoti Das; 20.01.2014
comment
Боюсь, вам следует: - либо обработать его на стороне приложения, создающего данные, - либо пропустить ваш входной файл через препроцессор - ваш код, который его прочитает и заменит все двойные апострофы на два двойных апострофа. Возможно, библиотека предоставляет такую ​​возможность. В противном случае ваш исходный файл не является допустимым CSV/TSV. Кстати, если я ответил на ваш вопрос, и наличие неэкранированных двойных апострофов было основной причиной вашей проблемы, не могли бы вы отметить мой ответ как ответ? :) Спасибо. - person Honza Zidek; 20.01.2014
comment
Файлы данных, которые у меня есть, могут иметь такие расхождения, и проблема в том, что размер данных огромен и может достигать 100 ГБ данных в одном файле ... поэтому я не могу спроектировать процессор, так как ему не хватает памяти, и я не могу найти способ справиться с этим во время чтения - person Subhrajyoti Das; 20.01.2014
comment
Я не понимаю этого. Как может процессору не хватать памяти? Просто создайте простую программу чтения и записи, прочитайте строки из одного файла, исправьте апострофы и запишите их в другой файл. Максимальное потребление памяти — это данные, необходимые для одной строки. Само собой сборщик мусора будет занят :) Под процессором я не подразумеваю один из CellProcessors, я просто имею в виду его вообще. - person Honza Zidek; 20.01.2014
comment
У вас есть ЕЩЕ один вариант. Если вы не используете символ двойного апострофа в качестве символа кавычек, вы можете изменить CsvPreference — см. supercsv.sourceforge.net/apidocs/org/supercsv/prefs/ — чтобы двойные кавычки не считались символом кавычек. - person Honza Zidek; 20.01.2014
comment
эй, Хонза ... Я не могу это исправить Ниже приведен образец данных ABC 1 2 3 1 2 3, если я попытаюсь обработать вышеуказанные данные, тогда он говорит, что неожиданный конец файла при чтении цитируемого столбца, начиная со строки 3 и заканчивая на строка 3 контекст=нуль - person Subhrajyoti Das; 25.02.2014
comment
Привет, Субхраджьоти, из-за того, что в комментарии заканчивается удаленная строка, я не уверен, какие у вас входные данные... - person Honza Zidek; 25.02.2014
comment
Привет, Хонза, это одна строка выборочных данных ABC 1 2 3 1 2 3, разделенных табуляцией, каждая из которых представляет собой одну ячейку ... теперь, когда supercsv пытается прочитать, она займет 1 2 как одну ячейку, так как все между ними считается как в та же ячейка и, следовательно, не хватает данных и выдает ошибку: внезапный конец файла - person Subhrajyoti Das; 26.02.2014
comment
Как вы установили CsvPreference? public CsvPreference.Builder(char quoteChar, int delimiterChar, String endOfLineSymbols) Вы должны установить для quoteChar что-то, что НЕ является двойным апострофом, delimiterChar для того, что вы используете для разграничения полей. И передайте свой экземпляр CsvPreference в CsvBeanReader. Разместите здесь свой код или дайте мне свой адрес электронной почты, чтобы мы могли сообщить о коде. - person Honza Zidek; 26.02.2014
comment
Не знаю, использовали ли вы мой пример в решении буквально (чего не следовало) - возможно, вам придется заменить ',' на '\t' :) и не забыть передать в конструктор CsvBeanReader(. .., МОИ_ПРЕФЕРЕНЦИИ); - person Honza Zidek; 26.02.2014

Если вы используете синтаксический анализатор CSV для анализа ввода TSV, у вас будут плохие времена. Используйте правильный парсер TSV. uniVocity-parsers поставляется с парсером/записывающим устройством TSV. Вы также можете использовать аннотированные java-бины для анализа вашего файла непосредственно в экземплярах класса.

Примеры:

Этот код анализирует TSV как строки.

TsvParserSettings settings = new TsvParserSettings();

// creates a TSV parser
TsvParser parser = new TsvParser(settings);

// parses all rows in one go.
List<String[]> allRows = parser.parseAll(new FileReader(yourFile));

Используйте анализ BeanListProcessor в java-бинах:

BeanListProcessor<TestBean> rowProcessor = new BeanListProcessor<TestBean>(TestBean.class);

TsvParserSettings parserSettings = new TsvParserSettings();
parserSettings.setRowProcessor(rowProcessor);

TsvParser parser = new TsvParser(parserSettings);
parser.parse(new FileReader(yourFile));

// The BeanListProcessor provides a list of objects extracted from the input.
List<TestBean> beans = rowProcessor.getBeans();

Вот как выглядит класс TestBean: class TestBean {

// if the value parsed in the quantity column is "?" or "-", it will be replaced by null.
@NullString(nulls = { "?", "-" })
// if a value resolves to null, it will be converted to the String "0".
@Parsed(defaultNullRead = "0")
private Integer quantity;


@Trim
@LowerCase
@Parsed(index = 4)
private String comments;

// you can also explicitly give the name of a column in the file.
@Parsed(field = "amount")
private BigDecimal amount;

@Trim
@LowerCase
// values "no", "n" and "null" will be converted to false; values "yes" and "y" will be converted to true
@BooleanString(falseStrings = { "no", "n", "null" }, trueStrings = { "yes", "y" })
@Parsed
private Boolean pending;

Раскрытие информации: я являюсь автором этой библиотеки. Это бесплатно и с открытым исходным кодом (лицензия Apache V2.0).

person Jeronimo Backes    schedule 23.11.2014