Универсальный парсер CSV-файлов


В интернете довольно много примеров, как парсить CSV-файл.
Но ни один из них не смог сразу прочитать правильно CSV-файл от MS Exchange!
Данный парсер не только может корректно это сделать, но и читает любые CSV-файлы от других программ.

CSV (от англ. Comma-Separated Values — значения, разделённые запятыми) — текстовый формат, предназначенный для представления табличных данных. Каждая строка файла — это одна строка таблицы. Значения отдельных колонок разделяются разделительным символом (delimiter) — запятой (,). Однако, большинство программ вольно трактует стандарт CSV и допускают использование иных символов в качестве разделителя. 

 

За основу кода взята типовая функция РазложитьСтрокуВМассивПодстрок.

// Функция "расщепляет" строку на подстроки, используя заданный
//  разделитель. Разделитель может иметь любую длину.
//  Если в качестве разделителя задан пробел, рядом стоящие пробелы
//  считаются одним разделителем, а ведущие и хвостовые пробелы параметра Стр
//  игнорируются.
//  Например,
//  РазложитьСтрокуВМассивПодстрок(",ку,,,му", ",") возвратит массив значений из пяти элементов,
//  три из которых - пустые строки, а
//  РазложитьСтрокуВМассивПодстрок(" ку   му", " ") возвратит массив значений из двух элементов
//
// Параметры:
//  Стр -    строка, которую необходимо разложить на подстроки.
//      Параметр передается по значению.
//  Разделитель -  строка-разделитель, по умолчанию - запятая.
//
//
// Возвращаемое значение:
//  массив значений, элементы которого - подстроки
//
Функция РазложитьСтрокуВМассивПодстрок(Знач Стр, Разделитель = ",") Экспорт

МассивСтрок = Новый Массив();
Если Разделитель = " " Тогда
Стр = СокрЛП(Стр);
Пока Истина Цикл
Поз = Найти(Стр,Разделитель);
Если Поз=0 Тогда
МассивСтрок.Добавить(Стр);
Возврат МассивСтрок;
КонецЕсли;
МассивСтрок.Добавить(Лев(Стр,Поз-1));
Стр = СокрЛ(Сред(Стр,Поз));
КонецЦикла;
Иначе
ДлинаРазделителя = СтрДлина(Разделитель);
Пока Истина Цикл
Поз = Найти(Стр,Разделитель);
Если Поз=0 Тогда
МассивСтрок.Добавить(Стр);
Возврат МассивСтрок;
КонецЕсли;
МассивСтрок.Добавить(Лев(Стр,Поз-1));
Стр = Сред(Стр,Поз+ДлинаРазделителя);
КонецЦикла;
КонецЕсли;

КонецФункции // глРазложить

Это функция дополнена параметром СимволВыделения! Этот параметр решает проблему выделения ячеек, в которых присутствует разделитель.

В разработке использовался код: Работа в 1С с CSV файлами. 

Для ознакомления в модуле есть код: //infostart.ru/public/98398/.

Обновление от 30.10.2024

Дописан алгоритм вычленения ячеек, в которых есть и символ разделитель, и символ выделения.

Например, строка: «Ответ на письмо», мой друг» доставлен».  Вернятся как: Ответ на письмо», мой друг» доставлен.

В прошлой версии результат был: Ответ на письмо| мой друг» доставлен.

16 Comments

  1. Yashazz

    Автор, а вы в курсе, что читать csv-файлы как текст — это жесть, допустимая только при маленьком их размере или откровенно кривом формате? Это я к тому, что заголовочек у публикации больно сомнителен — «универсальный парсер», ага. Универсальные, во-первых, давно есть, а во-вторых, не через «Разложить строку» делаются)

    Reply
  2. Xershi

    (1) Yashazz, покажите мне универсальный, ссылку пожалуйста!

    Давайте я вам дам файл, а вы мне его корректно вашим парсером разложите?

    Reply
  3. V.Nikonov

    А как быть со строковыми колонками которые в тексте содержат разделитель? По стандарту такие значения заключают в кавычки, и тогда разделитель до закрывающей кавычки не анализируется!

    Reply
  4. Xershi

    (3) V.Nikonov, после тестирования парсера на большом массиве строк, доработал код. Но пока нет времени обновить файл публикации. Так что в скором времени и этот вопрос будет решен.

    Но даже в текущей версии такую строку распарсит корректно, если рядом не будет символа выделения!

    Reply
  5. Xershi

    Немного статистики. CSV-файл более 2 ГБ обработка не смогла даже прочитала, т.к. просто вылетела платформа. А вот файл менее 1 ГБ обработало, но на 97% не хватило памяти на сервере и тоже вылет (процесс 1С использовал почти 3 гига оперативной памяти).

    Файл в 680 МБ с трудом дочитало (процесс 1С использовал почти 2.5 гига оперативной памяти).

    Файлы с меньшим объемом без проблем читает.

    Все операции выполнялись на 32-битном процессе. Как поведет себя обработка в регламентном задании, пока не могу сказать, но там используется 64-битный процесс, поэтому ограничение на память там больше.

    Познавательно по этому поводу написано на этом сайте: http://www.viva64.com/ru/k/0036/

    Reply
  6. BigB

    (0) функция РазложитьСтрокуВМассивПодстрокMSExchange работает неверно!

    Как видно из вложений в Excel csv открывается правильно, а в 1С неправильно.

    Из Вашей обработки я взял только одну функцию.

    Reply
  7. Xershi

    (6) BigB, вы настройки для своего конфигурации сделали? На скриншотах этого я не увидел.

    Reply
  8. BigB

    (7) повторю еще раз: Из Вашей обработки я взял только одну функцию.

    Запускал её с параметрами так:

    МассивКол = РазложитьСтрокуВМассивПодстрокMSExchange(Строка, «;», «»»»);
    Reply
  9. Xershi

    (8) BigB, так с такими параметрами, она будет работать по другому. Как типовая. Используйте полный список параметров!

    Reply
  10. BigB

    (9) приложил настройки из обработки.

    Только я не понял, чем они отличаются от моих, что я выложил ранее?

    Специально проверил Вашу загрузку. Мало того, что она не отработала нормально даже шапку файла, так и табличная часть была пустой!

    Reply
  11. Xershi

    (10) BigB, у вас шапка есть? Похоже строки шапки либо нет, либо разделитель у вас не тот. Взять только эту функцию будет не достаточно для корректной работы всего алгоритма! Используйте обработку полностью!

    Reply
  12. BigB

    (11) Вы почему не умеете читать, то, что Вам пишут? Я же Вам только, что написал и картинки приложил. Повторю ещё раз: При использовании Вашей обработки с настройками, которые я уже выкладывал — я получил кривую шапку (только последнюю колонку) и пустую табличную часть. В личку могу выслать csv файл, чтобы Вы сами убедиться, что функция РазложитьСтрокуВМассивПодстрокMSExchange не работает.

    Reply
  13. Xershi

    (12) BigB, скиньте в личку ваш файл. Важным нюансом также является, чтобы названия колонок шапки писались слитно!

    Думаю именно из-за этого у вас и не работает все. Поэтому, если вы весь алгоритм работы не разобрали, то такой результат и получили!

    Reply
  14. Xershi

    Ваш файл не по стандарту сделан.

    1. а.) В шапке нет разделителя! б.) И слова содержат пробелы. Для а.) я делал обновление http://infostart.ru/public/411000/. Для б.) убрать пробелы или заточить обработку под удаление пробелов в шапке.

    2. У вас разное количество колонок. В шапке 35, а в данных 36. Решается добавлением в шапку 36 колонки.

    Reply
  15. kuzyara

    Работающий код.

    Reply
  16. ZLENKO

    Реализовано в версии 8.3.6.1977 функции: СтрРазделить(), СтрСоединить()

    Читаем тут: https://infostart.ru/public/366865/

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *