Автоопределение CSV в Java - PullRequest
       22

Автоопределение CSV в Java

10 голосов
/ 19 декабря 2011

Какой надежный способ автоматического определения того, что файл на самом деле является CSV , если CSV был переопределен, чтобы обозначать «Значения, разделенные символами», то есть данные, использующие любой отдельный символ (но обычно любые не алфавитно-цифровыесимвол) как разделитель, а не только запятые?

По существу, с этим (пере) определением, CSV = DSV («Значения, разделенные разделителями»), обсуждаемые, например, в этом статья в Википедии , тогда как формат «Значения, разделенные запятыми» определен в RFC 4180 .

Более конкретно, существует ли метод для статистического вычитанияданные имеют как-то «фиксированную» длину , что означает «возможный CSV»?Простой подсчет количества разделителей не всегда работает, потому что существуют CSV-файлы с переменным числом полей на запись (т. Е. Записи, которые, в отличие от мандатов RFC 4180, не имеют одинакового количества полейчерез тот же файл).

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

Proper ("full ") Для автоопределения требуется как минимум 4 решения , которые должны быть приняты надежно:

  1. Обнаружение того, что файл действительно является CSV
  2. Обнаружение наличия заголовков
  3. Обнаружение фактического символа разделителя
  4. Обнаружение специальных символов (например, кавычек)

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

Таким образом, наилучшим подходом, кажется, является телескопическаяобнаружение , в котором форматы, которые также могут быть классифицированы как CSV (например, форматы файлов журнала, такие как Apache CLF), проверяются перед применением.один из правил обнаружения CSV.

Даже коммерческие приложения, такие как Excel, похоже, полагаются на расширение файла (.csv), чтобы выбрать (1), что, очевидно, не является автоматическим определением, хотя проблема значительно упрощенаесли приложению сообщают, что данные представляют собой CSV.

Вот несколько хороших соответствующих статей, обсуждающих эвристику для (2) и (3):

Обнаружение (4), типа кавычек, может быть основано на обработке нескольких строк из файла и поиске соответствующих значений (например, четное число «или» в строке будет означать одинарные или двойные кавычки).Такая обработка может быть выполнена посредством инициализации существующего синтаксического анализатора CSV (например, OpenCSV ), который будет должным образом заботиться о разделении строк CSV (например, многострочные события).

Но как насчет (1), т. е. решив, что данные CSV в первую очередь?

Может ли data mining помочь в этом решении?

Ответы [ 2 ]

6 голосов
/ 20 декабря 2011

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

Вы можете выполнить итерацию всех возможных комбинаций символа кавычки, разделителя столбца и разделителя записи (256 * 255 * 254 = 16581120 для ASCII).

id,text,date
1,"Bob says, ""hi
..."", with a sigh",1/1/2012

Удалить все цитируемые столбцы, это можно сделать с помощью замены RegEx.

//quick javascript example of the regex, you'd replace the quote char with whichever character your currently testing
var test='id,text,date\n1,"bob, ""hi\n..."", sigh",1/1/2011';
console.log(test.replace(/"(""|.|\n|\r)*?"/gm,""));

id,text,date
1,,1/1/2012

Разделить на разделитель записи

["id,text,date", "1,,1/1/2012"]

Разделение записей по разделителю столбцов

[ ["id", "text", "date"], ["1", "", "1/1/2012"] ]

Если количество столбцов в одной записи совпадает, у вас есть уверенность в CSV.

3 == 3

Если количество столбцов не совпадает, попробуйте другую комбинацию символа строки, столбца и кавычки

EDIT

Фактический анализ данных после того, как у вас есть уверенность в разделителях и проверка на однородность типа столбца, может быть полезным дополнительным шагом

  • Все ли столбцы в строке первой (заголовка?) Строки
  • Всегда ли столбец X разбирается на ноль / пустое или действительное (int, float, date)

Чем больше CSV-данных (строк, столбцов) нужно использовать, тем больше уверенности вы сможете извлечь из этого метода.

Я думаю, что этот вопрос является довольно глупым / чрезмерно общим, если у вас есть поток неизвестных данных, который вы определенно хотели бы сначала проверить для всех "низко висящих фруктов". Бинарные форматы обычно имеют довольно разные сигнатуры заголовков, а также XML и JSON для легко обнаруживаемых текстовых форматов.

1 голос
/ 19 декабря 2011

Всегда будут файлы, отличные от CSV, которые выглядят как CSV, и наоборот.Например, есть патологический (но совершенно правильный) CSV-файл, который Франк опубликовал в приведенной вами ссылке на Java:

Name
Jim
Tom
Bill

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

  1. Есть символ-кандидат-разделитель, который появляется в каждой строке (или, если хотите, у каждой строки есть один токен).
  2. Учитываясимвол-кандидат-разделитель, большинство (но не обязательно все) строк имеют одинаковое количество полей.
  3. Наличие первой строки, которая выглядит так, как будто это заголовок, увеличивает вероятность файла, содержащего данные CSV.

Возможно, можно придумать другую эвристику.Тогда подход должен был бы разработать алгоритм оценки, основанный на нихСледующим шагом будет оценка коллекции известных файлов CSV и не CSV.Если существует достаточно четкое разделение, то оценка может быть сочтена полезной, и оценки должны подсказать вам, как установить порог обнаружения.

...