Лучший способ обработки файлов с разделителями

16

Поэтому обычно CSV-файл использует запятую и символ возврата в качестве разделителей полей и строк.

Это наталкивается на очевидные проблемы с текстом, который может содержать оба этих символа.

Очевидно, что есть варианты (избегая их), но как люди справляются с этим? Использовать разных персонажей - трубы или тильды? Сбежать от них? Не использовать файлы с разделителями, ведь сейчас 2010 год, и теперь у нас есть XML?

Поищите хотя бы усилия для достойного шанса не увидеть проблем.

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

Джон Хопкинс
источник
Тщательно подумайте об использовании CSV - с ним приятно и легко иметь дело (см. Ответы по общим правилам экранирования), но это не так удобно, как должно быть - если вы просто общаетесь с собственными программами, это нормально, но если вы хотите импортировать в другое место, это становится немного странным, потому что разные программы подчиняются различным правилам escape.
Майкл Кохне
@ Майкл - Абсолютно. Проблема в том, что это настолько вездесуще, что вы почти всегда будете сталкиваться с ситуациями, когда это очень заманчивый вариант, а в случае многих старых систем это единственный вариант.
Джон Хопкинс
Зрелые библиотеки существуют на многих языках (безусловно, распространенных) для чтения и записи файлов с разделителями символов. Они справятся практически с любой ситуацией. Написание собственного синтаксического анализатора CSV, похоже, является распространенным анти-паттерном.
Квентин Старин

Ответы:

13

Согласно Википедии :

Поля со встроенными запятыми должны быть заключены в двойные кавычки.

И, кроме того:

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

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

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

Joonas Pulakka
источник
3
Что должно быть, а что есть .. часто отличается :)
Тим Пост
Я думаю, что решение вполне нормально. Для простых данных, CSV работает отлично, для сложных данных , то цитирование является necesary, и побег "с„“следы обратно в BASIC.
Ernelli
1
@ Эрнелли: Теперь, когда я думаю об этом больше, это может быть разумный компромисс между удобочитаемостью и простотой. Проблема заключается в том, что для людей это выглядит некрасиво , хотя для компьютера это тривиально . Таким образом, резервирование escape-символов только в редких случаях («поля со встроенными символами в двойных кавычках») приводит к выводу, который обычно выглядит вполне понятным для человека. Это хорошее решение, если предположить, что запятые в именах полей используются чаще, чем двойные кавычки в именах полей.
Joonas Pulakka
2

Я предполагаю, что у вас есть что-то вроде этого:

Foo,Baz,,,"Foo,Baz"

Если строки, содержащие разделитель не указаны или убежали, вы не имеете реальный надежный способ разбора файла.

Вы можете, однако, изучить данные для анализа и сделать такие выводы:

  • Поплавки через запятую следует рассматривать как строку
  • Если строка до или после этого содержит меньше разделителей, пропустите анализ этой строки и зарегистрируйте ее
  • Относитесь к «как»

Вы должны написать парсер для обработки подобных вещей, но это не должно быть сложным.

По моему опыту, импорт массивных дампов из чего-то вроде Excel всегда приводит к необходимости вернуться назад и просмотреть некоторые странности. Ваша задача состоит в том, чтобы дать вашей программе только достаточно здравого смысла в отношении данных , так что он не делает сумасшедшие вставки. Затем просмотрите, что было зарегистрировано и вымойте / ополосните / повторите.

Однажды я написал внутренний FAQ для небольшой компании, которая использовала все рабочие станции Ubuntu. Часть FAQ содержала «горячие клавиши», и мне пришло в голову разделитель. Ну, ответы, как правило, также были разделены символом (например, grep foo | что-то) и не заключены в кавычки или не экранированы. Я чувствую эту боль :)

Тим Пост
источник
2

Ничего плохого в CSV до определенного момента

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

Вот удобный список больших ошибок:

  1. Экранирование "" в пределах "" (поле содержит разделитель полей)
  2. "", содержащие CRLF (поле содержит разделитель строк)
  3. Юникод (основной текстовый формат может быть недостаточным)
  4. Разные линейные терминаторы для разных ОС (это CR или CRLF или LF или NUL?)
  5. Встроенные комментарии (строка с префиксом #, //, -,; и т. Д.)
  6. Управление версиями (последняя версия файла содержит больше или меньше полей)
  7. Различие между NULL и пустыми данными (, "", пусто, но ,, является нулем?)

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

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

В целом, если вы просто ищете простой способ обработки файлов такого типа, то в мире Java вы можете просто использовать OpenCSV . Таким образом вы абстрагируете все проблемы в установленные рамки.

Гэри Роу
источник
2

CSV по-прежнему является допустимым форматом во многих ситуациях, тем более что для клиента это все же самый простой способ записать данные, которые необходимо импортировать в ваше приложение. Мало кто из наших клиентов любит иметь дело с XML, возможно, потому что он очень многословен и имеет все эти «страшные» угловые скобки. Им гораздо проще обернуть свои мозги вокруг простого списка элементов, разделенных согласованным символом, а также согласиться с тем, что один и тот же символ не будет разрешен в содержимом поля.

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

Дейв
источник
1

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

это зависит от ситуации, какой формат будет использоваться, и CSV является разумным форматом для обмена простыми структурами формата данных.

Salandur
источник
0

Забудьте CSV, используйте JSON . Легко написать, легко разобрать. XML это так 2005 .

user281377
источник
6
и имеет ту же проблему, когда вы хотите использовать символ, который является частью формата JSON (например, {или,)
Salandur 14.12.10
Саландур: Совсем нет! Есть точные правила, как убежать! Но {и, даже не нужно избегать, потому что внутри строки, они не являются двусмысленными!
user281377 14.12.10
1
Ну и хорошо, но я не припомню, чтобы в Excel была функция «Экспорт в JSON» :) Бывают случаи, когда приходится разбирать нечетные вещи, хотя бы для того, чтобы перевести их в более приятный формат.
Тим Пост
1
И JSON просто великолепен для передачи миллиона объектов одинаковой формы. Ой, подожди.
Фрэнк Шиарар
1
JSON не предлагает никаких улучшений по сравнению с CSV в отношении этого вопроса и, по крайней мере, не обладает совместимостью со многими приложениями (как уже упоминалось, не может импортировать или экспортировать из Office, баз данных SQL и т. Д.). JSON отлично подходит для внутренних, легких операций на стороне клиента, но XML намного лучше для передачи данных между приложениями.
Дэн Диплом
0

Обычно я получаю TSV (значения, разделенные табуляцией), а не CSV-файл, перетаскиваю файл в Emacs и вижу, какой из нескольких необычных символов он НИКОГДА не использует ($ обычно здесь хороший выбор), а затем я конвертирую все вкладки в $.

Оттуда GNU AWK можно сказать использовать $ в качестве разделителя полей, а Боб - твой дядя.

Джон Р. Штром
источник