Ограничить CsvListReader одной строкой

Я работаю над приложением, которое обрабатывает большие файлы CSV (несколько сотен МБ). Недавно я столкнулся с проблемой, которая сначала выглядела как утечка памяти в приложении, но после некоторого расследования оказалось, что это комбинация плохо отформатированного CSV и попытки CsvListReader разобрать бесконечную строку. В результате я получил следующее исключение:

at java.lang.OutOfMemoryError.<init>(<unknown string>)
at java.util.Arrays.copyOf(<unknown string>)
   Local Variable: char[]#13624
at java.lang.AbstractStringBuilder.expandCapacity(<unknown string>)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(<unknown string>)
at java.lang.AbstractStringBuilder.append(<unknown string>)
at java.lang.StringBuilder.append(<unknown string>)
   Local Variable: java.lang.StringBuilder#3
at org.supercsv.io.Tokenizer.readStringList(<unknown string>)
   Local Variable: java.util.ArrayList#642
   Local Variable: org.supercsv.io.Tokenizer#1
   Local Variable: org.supercsv.io.PARSERSTATE#2
   Local Variable: java.lang.String#14960
at org.supercsv.io.CsvListReader.read(<unknown string>)

Анализируя дамп кучи и файл CSV на основе результатов дампа, я заметил, что в одном из столбцов в одной из строк CSV отсутствовали закрывающие кавычки, что, очевидно, приводило к тому, что читатель пытался найти конец строки, добавляя содержимое файла во внутренний строковый буфер, пока не будет больше не было кучи памяти.

Во всяком случае, это была проблема, и это было из-за плохо отформатированного CSV - как только я удалил критическую строку, проблема исчезла. Чего я хочу добиться, так это сказать читателю, что:

  • Весь контент, который он должен интерпретировать, всегда заканчивается символом новой строки, даже если кавычки не закрыты должным образом (без многострочной поддержки).
  • В качестве альтернативы, чтобы обеспечить определенный предел (в байтах) строки CSV

Есть ли какой-то четкий способ сделать это в SuperCSV с помощью CsvListReader (предпочтительнее в моем случае)?


person dstefanox    schedule 05.03.2013    source источник


Ответы (1)


Об этой проблеме сообщалось, и я работаю над некоторыми улучшениями (на будущее основной выпуск) на данный момент это должно сделать оба варианта немного проще.

На данный момент вам придется предоставить считывателю свой собственный токенизатор (поэтому Super CSV использует ваш, а не свой). Я предлагаю взять копию Tokenizer Super CSV и изменить с вашими изменениями. Таким образом, вам не нужно изменять Super CSV, и вы не будете тратить время впустую.

person James Bassett    schedule 05.03.2013
comment
Спасибо за ваш ответ, внесение небольших изменений в Tokenizer и его использование, как вы предложили, позволило мне предотвратить проблемы с памятью и настроить Super CSV для моего варианта использования. Возможно, было бы неплохо создать немного более настраиваемый токенизатор и сделать его стандартной частью библиотеки Super CSV. Буду рад помочь в этом. - person dstefanox; 06.03.2013