7 правил RFC 4180

Публикация № 541555

Программирование - Универсальные функции

ТЗ ТаблицаЗначений формат CSV импорт экспорт RFC 4180 ADO OLEDB

22
Что такое CSV? Описание правил формата RFC4180 и пара функций чтения/записи CSV текста в ТЗ согласно этим рекомендациям (с экранированием и _поддержкой многострочных полей_).

По мотивам... Перевод документа с ietf.org:

Правило №1: Каждая запись (record) начинается с новой строки. (CRLF, #13#10, U+000D U+000A)

1. Each record is located on a separate line, delimited by a line
   break (CRLF).  For example:

   aaa,bbb,ccc CRLF
   zzz,yyy,xxx CRLF

Правило №2: Последня запись может оканчиваться переносом строки.

2. The last record in the file may or may not have an ending line
   break.  For example:

   aaa,bbb,ccc CRLF
   zzz,yyy,xxx

Правило №3: Опционально первая строка может являться заголовком, содержащим имена колонок.

3. There maybe an optional header line appearing as the first line
   of the file with the same format as normal record lines.  This
   header will contain names corresponding to the fields in the file
   and should contain the same number of fields as the records in
   the rest of the file (the presence or absence of the header line
   should be indicated via the optional "header" parameter of this
   MIME type).  For example:

   field_name,field_name,field_name CRLF
   aaa,bbb,ccc CRLF
   zzz,yyy,xxx CRLF

Правило №4: Поля разделены запятыми (разделителем). Заждая запись имеет одинаковое количество полей. Пробелы являются частью полей и не должны игнорироваться. После последнего поля не может быть запятой.

4. Within the header and each record, there may be one or more
   fields, separated by commas.  Each line should contain the same
   number of fields throughout the file.  Spaces are considered part
   of a field and should not be ignored.  The last field in the
   record must not be followed by a comma.  For example:

   aaa,bbb,ccc

Правило №5: Каждое поле может быть заключено в двойные кавычки. Если поле не заключено в двойные кавычки, то внутри уже не может находится сивол двойных кавычек. (По-умолчанию поле заключается в кавычки, если требуется экранирование, см. правило 6)

5. Each field may or may not be enclosed in double quotes (however
   some programs, such as Microsoft Excel, do not use double quotes
   at all).  If fields are not enclosed with double quotes, then
   double quotes may not appear inside the fields.  For example:

   "aaa","bbb","ccc" CRLF
   zzz,yyy,xxx

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

6. Fields containing line breaks (CRLF), double quotes, and commas
   should be enclosed in double-quotes.  For example:

   "aaa","b CRLF
   bb","ccc" CRLF
   zzz,yyy,xxx

Правило №7: Если поле заключено в двойные кавычки, то кавычки внутри поля должны быть экранированы предшествующими кавычками.

7. If double-quotes are used to enclose fields, then a double-quote
   appearing inside a field must be escaped by preceding it with
   another double quote.  For example:

   "aaa","b""bb","ccc"

ABNF грамматика

   file = [header CRLF] record *(CRLF record) [CRLF] 
   header = name *(COMMA name) 
   record = field *(COMMA field) 
   name = field 
   field = (escaped / non-escaped) 
   escaped = DQUOTE *(TEXTDATA / COMMA / CR / LF / 2DQUOTE) DQUOTE 
   non-escaped = *TEXTDATA 

Примечания:

На практике под CSV часто понимают более общий формат DSV (delimiter-separated values,
значения, разделенные разделителем), который может использовать отличные от запятой
разделители. Наиболее популярные в нашей стране разделители – символ табуляции и точка
с запятой. Причем некоторые программы, как, например, Microsoft Excel, могут исполь-
зовать тот или иной разделитель в зависимости от региональных настроек (в MS Excel –
запятая в общих настройках и точка с запятой в российских)
.

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

Дополнения W3C:

  • Имена файлов должны заканчиваться расширением .csv.
  • Файлы должны иметь кодировку UTF-8.
  • Файлы должны иметь одну строку заголовка. Эта строка должна быть первой строкой в файле.
    • Каждый столбец в файле CSV называется полем и его имя находится в строке заголовка в том же столбце .
    • Имя столбца должно быть уникальным среди полей заголовка, содержать по крайней мере один символ.
  • Строки в файле не должны содержать больше полей, чем в строке заголовка (хотя они могут содержать меньше).
  • Если CSV файл не следует этим правилам, то его специфический CSV диалект должен быть документирован согласно CSV Dialect Description Format.
 
 ТЗ в CSV
Процедура ПреобразоватьТЗвТекстCSV(ИмяФайла, ТЗ, Разделитель = ";", флЭкспортироватьИменаКолонок = Ложь)
		
	//ТекстДок = Новый ТекстовыйДокумент; // вызывает проседание при конкатенации >10 тыс. строк
	ЗаписьТекста = Новый ЗаписьТекста(ИмяФайла);
	
	Если флЭкспортироватьИменаКолонок Тогда
		//Если нужно выгружать наименование колонок Выгружаем
		ПодготовленнаяСтрока = "";
		Для Каждого Колонка Из ТЗ.Колонки Цикл
			ПодготовленнаяСтрока = ПодготовленнаяСтрока + Колонка.Заголовок + Разделитель;
		КонецЦикла;
		ПодготовленнаяСтрока = Лев (ПодготовленнаяСтрока,СтрДлина(ПодготовленнаяСтрока)-1);
		
		//ТекстДок.ДобавитьСтроку(ПодготовленнаяСтрока);
		ЗаписьТекста.ЗаписатьСтроку(ПодготовленнаяСтрока);
	КонецЕсли;
	
	Для Каждого Строка Из ТЗ Цикл
		ПодготовленнаяСтрока = "";
		Для Каждого Значение Из Строка Цикл ПодготовленнаяСтрока = ПодготовленнаяСтрока + """" + Значение + """"+ Разделитель; КонецЦикла; // в одно строку, т.к. так реально быстрей
		//Для Каждого Колонка Из ТЗ.Колонки Цикл
		//	ПреобразованноеПоле = Строка[Колонка.Имя];
		//	//по правилам CSV если поле содержит двойные кавычки они должны повторятся дважды
		//	//Если Найти(ПреобразованноеПоле,"""") Тогда
		//	//	ПреобразованноеПоле = СтрЗаменить(ПреобразованноеПоле,"""","""""");
		//	//КонецЕсли;
		//	////по правилам CSV если поле содержит перенос строки или запятую оно должно заключатся в двойные кавычки
		//	//Если Найти(ПреобразованноеПоле,Разделитель) ИЛИ Найти(ПреобразованноеПоле,Символы.ПС) ИЛИ Найти(ПреобразованноеПоле,"""") Тогда
		//	//	ПреобразованноеПоле = """" + ПреобразованноеПоле + """";
		//	//КонецЕсли;

		//	ПодготовленнаяСтрока = ПодготовленнаяСтрока + """" + ПреобразованноеПоле + """"+ Разделитель;
		//КонецЦикла;
		ПодготовленнаяСтрока = Лев (ПодготовленнаяСтрока,СтрДлина(ПодготовленнаяСтрока)-1);
		
		//ТекстДок.ДобавитьСтроку(ПодготовленнаяСтрока);
		ЗаписьТекста.ЗаписатьСтроку(ПодготовленнаяСтрока);
	КонецЦикла;
	ЗаписьТекста.Закрыть();
КонецПроцедуры
 
 CSV в ТЗ
 
 Чтение данных с помощью ADODB.Connection
 
 Чтение данных с помощью GameWithFire.dll

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

Ссылки:

1. IETFRFC 4180. Common Format and MIME Type for CSV Files
2. W3C. See sparql11-results-csv-tsv, the first W3C recommendation scoped in CSV and filling some of RFC4180's lacks
3. RFC 4180, спецификация (рус.)
4. JSON Data SpecificationsCSV Dialect Description Format (CSVDDF)

upd: для чтения больших файлов данный код совершенно не годится, лучше использовать adodb или gamewithfire,
вот сравнение времени выполнения методов для файла из 10000 строк:

  • Native - 28 578 мс
  • ADODB - 8 336 мс
  • GWF - 7 236 мс

github: Исходный код

22

Скачать файлы

Наименование Файл Версия Размер
ПреобразованиеCSVвТЗ.epf
.epf 11,98Kb
21.08.16
15
.epf 1.0 11,98Kb 15 Скачать

См. также

Специальные предложения

Комментарии
Избранное Подписка Сортировка: Древо
1. rise 05.04.17 17:50 Сейчас в теме
А вот такая строка неверно читается
aaa,"","ccc"

Получается
aaa,", ccc
4. kuzyara 754 11.06.19 05:08 Сейчас в теме
(1)
aaa,"","ccc"

ну почему же, читается
разделитель не выставили?
Прикрепленные файлы:
Оставьте свое сообщение