Как стать автором
Обновить

Комментарии 157

А если сконвертировать в строчку, по-типу "01-02-2024", то это создаст
новую проблему - в США сначала идёт месяц, а потом день, у нас же
сначала день, а потом месяц. И "01-02-2024" они прочитают не как 1
февраля 24го, а как 2 января. И у меня нет идей, как решать такое. А
какие у Вас есть мысли?

Можно использовать ISO формат YYYY-MM-DD: "2024-02-01" — это будет восприниматься однозначно всеми системами

Здесь все сложнее. В десктопных приложениях, типа MS Excel, формат данных при экспорте в csv и импорте обратно определяется системными региональными настройками (locale) у пользователя. Корни такого поведения уходят в глубокую древность и до сих пор ни кто не решился это исправить, чтобы не ломать обратную совместимость.

В US формат дат по умолчанию MM-DD-YYYY, а в качестве разделителя дробей используется точка. Разделитель ячеек - запятая. Здесь две ячейки:

123.4556,04-12-2023

В Европе чаще DD.MM.YYYY, а дробная часть числа отделяется от целой - запятой. Поэтому ячейки разделяются точкой с запятой. Вот так будет представлено то же самое:

123,4556;12.04.2023

На практике строка:

3,14

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

Как вам и написали, формат YYYY-MM-DD (ISO 8601) позволит избежать разночтений.

Как вам и написал, формат дат при экспорте из Excel определяется локалью пользователя. Вы на это ни как не можете влиять.

Нет, ну можете сходить к каждому бухгалтеру и поменять настройки системы, но тогда время у него будет отображаться в ISO 8601 вообще везде, а не только в csv, за что он конечно будет вам безумно благодарен.

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

Подключаюсь клиентом к MS SQL Server-у. Для выборки данных из таблицы приходится указывать дату(where clause) в формате YYYY-DD-MM. Потому даже здесь нужно "договариваться заранее"

Для таких вещей в mssql правильно использовать datefromparts.

В mssql однозначно и правильно работает формат YYYYMMDD,а с минусами иногда приходит именно в DD-MM,а не привычном всем

1) Если это Телеграм-бот, то можно определить язык системы и по нему сгенерировать дату в правильном формате;

2) Ввести параметр для указания формата выдачи даты.

Предложение использовать базу данных sqlite мне кажется неплохим вариантом. Там не будет: может так, а может эдак!

У меня была задача - работа именно с Excel файлами. Их бухгалтеры ни про какую sqlite не в курсе.

Вот я прочитал и вроде даже понял, что у чувака пригорело по поводу использования листов эксель для хранения данных и получения данных из них. Единственное, не понял, почему у него пригорело? Можете пояснить или ткнуть носом в кусок текста?

Потому что завязывать бизнес процесс на технологию, реализованную странно, криво, неудобно - это создание огромной бомбы замедленного действия. Он же пишет и я с ним полностью согласен, что проблемы, создаваемые такими решениями (включением excell/csv как один из обязательных в бизнеспроцессе, даже когда данные передаются между машинами) в последствии стоят компании огромных денег, и решать их очень противно (тем кто писал на том же vba после условного python) но и выгодно.

а откуда они эти файлы берут?
В бухгалтерской 1С собственно sql чаще чем что-либо другое

Бухгалтер sql не видит никогда. Но у него есть кнопка с экспортом..

Так то бухгалтер.
Но мы же про статью - выходит, что вместо того, чтобы взять данные прямо из sql, тут сперва просят бухгалтера руками нажать тысячи экспортов, а потом "пишут" библиотеку по их парсингу назад в sql/cvs?

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

Именно так все и делают. Первые выкапывают ямы, а вторые закапывают.

Особенно больно смотреть про всякие регламенты обмена всякими данными между организациями. Вместо того, чтобы договориться хоть о какой-то унификации формата, начинаются порождения сущностей. Например, когда в интерфейсе пользователя куча кнопок

  • Импорт договоров из Организации А

  • Импорт договоров из Организации Б

  • Импорт договоров из Организации В

  • Экспорт отчетов в Организации А

  • Экспорт отчетов для Организации Б

  • Экспорт отчетов опять для Организации А старый формат для бухгалтера

Тут как раз соседняя статья была про такое

https://habr.com/en/companies/itq_group/articles/765882/

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

С одной стороны, монополии поддерживать неохота
А с другой стороны, для стандартов нужно что то типа законодательства против вендорлока (оно очень сложное будет и даже если в этом направлении пошевелятся, десятилетиями будут разброд и шатания)

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

язык системы и по нему сгенерировать дату в правильном формате

Или в неправильном если формат дат настроен другой.

"В US формат дат по умолчанию MM-DD-YYYY" У них вообще все транректально. Мили, дюймы, дибильное время AM.PM, хотя гораздо понятнее формат 24 часа. Чего только стоят дюймовые шестигранники - Если метрический я сразу выбираю на глаз, то дюймовый иногда с третьего раза. Как они там живут со всеми этими галлонами - уму не постижимо.

Фаренгейты забыли.

О! Похоже тут человек, понимающий в региональных настройках Excel! Можно я напишу сюда свой вопрос с Хабра-вопросов, а то там мне никто не ответил?

Коротко суть: на компе с ENG US локалью (региональные настройки установлены на Россия, а excel 2013 установлен русской версии) при сохранении xls в CSV msdos теряются русские символы (заменяются на "?"). При этом на компе с RUS языком всё сохраняется корректно, русские символы читаемы. Даже когда я поменял на первом компе язык системы на RUS, проблема не решилась. В интернете только ненормальные варианты, типа "получение внешних данных" > "из текста" в excel, а потом руками править кодировку на каждое открытие файла.

Не могу найти, где глубоко при установке прописывается eng локаль для excel.

В пакете MS Office помнится вроде была отдельная программа для его языковых настроек...

Есть, и там уже выставлен русский по умолчанию

CSV msdos

полагаю он не знает такой кодировки попробуй выставить utf8 или лучше utf-16, последняя как я понимаю используется windows как основа и ей не придется конвертировать кодировку туда-сюда

но utf-16 могут не понять программы, читающие твой csv, т.е. после этого тебе придется его конвертировать уже сторонними средствами, каким-нибудь консольным iconv

Мне нужна именно та. И непонятно, почему офис на русском я языке не знает русский. Пригодится конвертировать на компе с русским языком системы

Наверное использует системные вызовы для этого?

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

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

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

при сохранении xls в CSV msdos

А что такое CSV msdos? В смысле, CSV в кодировке, которую использовал MS-DOS? Но он использовал множество кодировок и для кириллицы использовал CP866. Вероятно, вам нужно читать в этой кодировке.

А шрифты с кириллицей стоят? (не знаю, но предполагаю)

Думаю что использование русской локали - это единственное решение. Возможно поможет Locale Emulator чтобы не менять ее глобально.

Не знал, что такое есть. Не знаю, поможет ли, но точно в копилку софта. Спасибо!

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

100% не вспомню, но я там проверял, вроде как. Надо проверить еще раз, когда буду за тем компом. Спасибо

Рассказываю: да, эта настройка помогла. Что меня смутило, когда я пробовал это полгода назад, так это то, что файл всё равно не открывается правильно. То есть после сохранения xls в csv, русские символы меняются на иероглифы. Потом файл можно открыть в notepad++ и всё отображается правильно. Я не заменил, что на русской версии винды этот файл тоже открывается с иероглифами и подумал, что эта настройка не помогает. НО ВАЖНЫЙ НЮАНС! Если в пункте Language for non-unicode programs выставлен English, то после сохранения xls > csv русские символы меняются не на иероглифы, а на "?". То есть часть информации теряется, так как eng кодировка короче. При этом файлы весят одинаково.

Слева файл сохранён с RUS настройкой, а справа с ENG

Спасибо всем, кто накидал вариантов. Отдельное спасибо @Naves за подсказку с этим меню!

Даже когда я поменял на первом компе язык системы на RUS, проблема не решилась.

Вам нужна галочка "использовать этот язык для не-Unicode программ"

Если бы у меня возникла похожая проблема, я бы проверял локаль.

Тебе для винды нужно выбрать русский в локале. Только так помоему.

Я поменял локаль eng компа на rus, но не помогло. Похоже кодировка полетела где-то раньше при установке rus офиса на eng винду (русская локаль стояла второй, не основной)

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

Я сохраняю в том формате, что даёт Excel. Там это строка csv msdos чегототам. И выбора кодировки нет. С компа с русской изначально локалью всё ОК, а с английской не ОК

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

правда, то больше для отображения старых приложений в консоли... но мало-ли. 1С 7.7, например, в логах писала ахинею, пока там не поставишь руский.

В csv можно заключить колонку, содержащую запятую, в кавычки. Тогда всё норм проходит. Кавычки можно экранировать

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

Мне когда-то доводилось писать функции на php, которые из "01-02-2024" делают "02-01-2024".
Через посимвольное считывание.
С региональными настройками (да ещё и автозаменами в экселе), конечно, можно намучиться...
Единственный выход, мне кажется, это чётко знать - в каком формате строки приходят, и в каком нужно отдать.

У меня есть документ, в котором построчно идет список дней за 10-15 лет. В формате MM-DD-YYYY. Начиная с определенной даты формат меняется на DD-MM-YYYY. Сам Excel это обрабатывает в макросах корректно - с его точки зрения поменялся только формат представления. А вот когда я это читаю в Python - приходится городить "if date > xxx".

Мне когда-то доводилось писать функции на php, которые из "01-02-2024" делают "02-01-2024".Через посимвольное считывание.

Это наверное давно было, потому что начиная с php 5.3 (2009 год) можно учитывать локаль для объекта DateTime и задавать формат при парсинге.

https://www.php.net/manual/en/class.intldateformatter.php

https://www.php.net/manual/en/datetime.createfromformat

В американском формате даты пишут через слэш. Держу в курсе

Слэш тоже не показатель. В той Америке, которая сверху глобуса, 01/05/2023 - это пятое января, а в Америке, которая снизу глобуса, эта же дата - первое апреля. Даты надо сериализовать в ISO формат, его одинаково понимают на всех континентах и во всех странах.

Первое мая)

Еще и нумерация месяцев, видимо, сдвинута на 1 :)

В названии слово "вероятно", вероятно, стоит не на своем месте.

Я бы сказал, в названии слишком мало слова "вероятно"...

Полистал я код и не увидел конвертации в csv.

Например как в результате будет обработаны ячеки со строками, содержащими используемый сепаратор (запятую у тебя по умолчанию?), двойные ковычки - " или еще веселее - многострочные (т.е. символы \n\r кстати во всех вариациях)?

но при этом excel читается библиотеками, а не напрямую, а ведь xslt это текстовый xml, пожатый zip-ом, я подумал что речь идет об этой оптимизации?

p.s. одно время много работал с данными, которые разные разработчики обязательно передавали в csv.
Эта отвратительная практика засела в разработчиках (и не только начинающих) и не понятно как ее от туда выковыривать. ну есть же отличные сериализации, причем ничего делать не надо, бери готовые библиотеки и сохраняй xml/json, без ограничений формата, никаких проблем со вложенными массивами (ох как только не извращаются некоторые чтобы передать в ячейке массив).

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

Опубликовано, но не стал смотреть: pub async fn make_csv(file: String, separator: Option) {

если тулза позволяет разделители менять, то можно никогда не встречающиеся символы использовать: \v , \a и т.п.

Полистал я код и не увидел конвертации в csv.

Если Вы запустите код, то обнаружите, что он работает. Я, признаюсь честно, сам плохо понимаю то, за счёт чего он работает, но Вы всегда можете спросить у разработчика библиотеки, конкретно, вот касательно этого куска кода в examples.

Я, признаюсь честно, сам плохо понимаю то, за счёт чего он работает, но Вы всегда можете спросить у разработчика

Привет, Хабр! Не редко захожу, читаю, пришло время поделиться собственным опытом и маленьким поводом для гордости - только что я написал библиотеку, которая примерно в 33 раза быстрее, чем все иные решения, что я находил.

Я извиняюсь, у автора раздвоение личности в анамнезе, или статье не хватает плашки "перевод" (хотя у меня ощущение, что скорее плашки "я тут решил попиариться на чужом коде, но спалился")?

Прямым же текстом написано, как я это сделал.

"Дальше я нагуглил библиотеку calamine, и тупо из примеров разработчика взял кусок кода."

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

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

Если бы вы сказали, что написали пример работы с Node-API, то было бы честнее. Хотя для примера у вас слишком много кода и слишком мало пояснений и комментариев.

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

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

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

Ну, сделать что-то рабочее, не понимая как это сделалось - это прям хорошо))

Слушайте, что "отличного" в сериализации в xml? Парсится долго, данные на ровном месте опухают в разы, порой в десятки. IMHO, уж лучше csv, если формат данных позволяет. У меня вообще всегда выходило, что если данных много, доступ нужен быстрый, или, не дай бог, по сети надо гонять - лучше всего свой бинарный формат сочинить. Если данных немного, на скорость и размер пофиг, а сами данные не пойми как структурированы - ну, взять готовое, типа json/yaml/toml. Для каких случаев вот именно xml будет оптимальным выбором?

А зачем изобретать свой формат, если есть Protobuf, Avro, MessagePack и другие?

С остальным соглашусь.

Я пробовал использовать Protobuf под какую-то задачу - в целом, вроде, было приемлемо. Чем-то не понравилось, но дело было лет десять назад, поэтому чем именно, помню плохо - кажется, и оверхед по данным выходил больше, и сериализация-десериализация происходила дольше, чем с самопальным бинарным форматом, но это всё не сказать, чтобы критично - главное, там чтобы его использовать надо было заморочиться посильнее, чем, опять-таки, с самопальным форматом - там же, вроде, ажно целый DSL какой-то надо было освоить, и потом его отдельным специальным компилятором компилить? Фиг знает, наверное, для каких-то задач, в каких-то условиях это оправдано (быть может, когда прям много разных структур данных надо сериализовывать, реально задолбает каждый раз вручную писать?), но мне по-дефолту не приходит первым делом в голову protobuf.

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

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

Но да, может быть оверкиллом для чего-то совсем небольшого.

Для скорости гугл flatbuffers придумал.

Оно как, соберётся для МК с 4кб памяти ?

Данные знаете ли много откуда поступать могут....

А таблички не лучше будет в parquet запихать?

В sqlite. Несколько примитивно и типов мало, но читается приблизительно везде и на всем.

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

что "отличного" в сериализации в xml

из единственной что есть - это человекочитаемый текстовый формат, может быть просмотрен и отредактирован в любом текстовом редакторе. Есть огромное количество инструментов (начиная с xslt и xpath) и нативной поддержкой теми же браузерами. Редакторы, валидаторы, библиотеки,...

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

У любых других форматов недостатков будет больше. Json я рекомендую обычно только потому что программистам с ним работать максимально просто (формат не такой старый как xml и нет исторических наслоений в идеологии использования), есть много библиотек и поддержки в языках программирования/фреймворках, но GUI инструментов не так много как хотелось бы (браузер показывает с оговорками).

Бинарные форматы можно рекомендовать только если существуют для них инструменты, подходящие под задачу. Всякие protobuf и прочие для передачи данных из одного места в другое (экспорт например) максимально неудобен. С ним могут работать только программисты, инструментарий скуден (попробуйте сравните, как из командной строки сформировать запрос поиска элемента в xml/json и как вы будете писать для этого приложение на protobuf, сколько усилий на это понадобится). И всегда помним если задача передачи данных встает в максимально различающихся средах (например из приложения на java передать данные на веб-проект на php), т.е. нужна поддержка с обоих сторон.

Правильный подход - передавать данные в виде sql дампа базы данных (в идеале саму базу данных типа sqlite/.mdb ms access), так как это максимально заточенный инструмент по работе с данными с не заданной заранее структурой.

p.s. csv полюбили только по одной причине, он прост для тех кто привык работать только в excell, одно время это был безоговорочный стандарт по работе с данными, даже со всеми его недостатками
Но меня коробит, когда я вижу что его используют как инструмент передачи данных между приложениями.

человекочитаемый текстовый формат, может быть просмотрен и отредактирован в любом текстовом редакторе

Я, конечно, понимаю, что, в теории, это действительно так, но, глядя на подобные файлы на практике, честно говоря, не верю, что действительно кто-то этим занимается. Нет, какой-то маленький файлик типа конфиг - понятно, но вот прям из программы овердохера данных слить в xml-файл, а потом его в текстовом редакторе вручную редактировать??

Всякие protobuf (...) С ним могут работать только программисты (...) Правильный подход - передавать данные в виде sql дампа базы данных

Пардон, а с sql дампом могут работать не только программисты? Т. е., опять-таки, я понимаю - инструменты есть, в теории всё можно, но на практике кто у вас такое делает и зачем?

Вот буквально наблюдаю за пользователем, который открывает xml с экспортированными данными из одной программы и редактирует его, чтобы импортировать в другую. Ни сколько не программист.

Да sql это уже для программистов, но вопрос в их уровне. Sql это тоже текст, приличное количество начинающих программистов (их реально много), понимающих базы данных на минимальном уровне могут удалить из текста простой программой какие то строки, например строки ddl или отредактировать их вручную и отправить на исполнение отдельно. Мало того, с высокой вероятностью sql дамп от одной базы данных можно будет импортировать в другую (с минимальными правками) просто пытаясь это делать и реагируя на сообщения об ошибке, а вот с protobuf рядовой начинающий уже не справится, бинарный файл смотреть нечем, ни один gui инструмент не предлагает его ни посмотреть ни тем более отредактировать (помню игрался с protoCurl, где требовалось дополнительно искать собственно .proto файл со структурой, дико неудобно).

В xml вообще нет ничего хорошего, выкинуть и забыть.

А что прям такого плохого?

<dataset>
<row prop1="value1" prop2="value2" prop3="value3" />
...
</dataset>
{
  "dataset": [
    { "prop1": "value1", "prop2": "value2", "prop3": "value3" },
    ...
  ]
}

Экономия в символах копеечная. А вот XML из коробки имеет потоковые парсеры на чём угодно, хоть на утюге, передавать данные можно любого объёма. Есть валидация схемы из коробки, большой набор типов данных. Если рассматривать как человекочитаемый формат для передачи данных, а не для web/API, то XML подходит по-лучше. Выгрузки прайсов размерами в гигабайты, я бы никогда не стал делать в JSON, особенно, если рассчитано на самых разных клиентов.

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

Или это просто классический масс-хейт? Да, XML со всем приколами, типа NS и сложностями запихали в своё время во все дыры, куда надо, и куда не надо, но это вовсе не значит, что это плохой формат. Если применять по делу, то всё с ним в порядке. "Выкинуть и забыть" это что-то на юношеско-максималистском.

Открывается кучей программ, имеет стандартные представления типов данных (та же дата-время в XML представляется строго в формате ISO безо всяких культурных приколов), не имеет проблем с кодировкой и экранированием, при желании спокойно дополняется машиночитаемой схемой.

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

А вот YAML и TOML - это форматы для редактирования человеком, сериализовать что-либо в них смысла нет.

С yaml местами ещё вопрос для каких инопланетян он делался. Если вспомнить про существования yaml 1.1 и 1.2, приколы с boolean и несчастных норвежцев xD

Эта отвратительная практика засела в разработчиках (и не только начинающих)

Ну дело в том, что иногда это требование в ТЗ и некоторые люди просят такой формат, чтобы им было удобно читать данные. Условно если у вас есть записи в виде name,email,phone и предполагается, что этот отчет будет просматриваться человеком, JSON при всех своих достоинствах не всегда удобен для чтения людьми поэтому в целом от csv вряд ли уйдут.

csv с кучей полей читается в "сыром" виде ещё хуже чем JSON.

1,2,3,4,,,,,"Hello, world!",15.7,188
10,2,3,4,,,,,,15.7,179
1,20,3,4,,8,,,,,196
1,2,,40,,,,9,,1,178

И такие вот "ребусы" я видел достаточно часто.

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

1,2,3,4,,,,,Hello, world!,15.7,188
10,2,3,4,,,,,,15.7,179
1,20,3,4,,8,,,,,196
1,2,,40,,,,9,,1,178

и вперёд

Ну, это уже нарушение правил экранирования в формате csv.

Хотя действительно, кого эти правила заботят?

Пхе, начитался тут и вспомнилось — довелось одну игру реверсить, которой сетевой протокол делали во времена до повсеместного распространения жсона. Поэтому в качестве key-value завёртки всего реквеста там был querystring, а внутри каждого поля — CSV с жёстко заданным порядком полей.

Начиналось всё неплохо — ну, например, надо передать список пройденных уровней, мы его и передаём: `10, 11, 14, 12`. А что если уровней меньше, чем размер массива? Ну тогда поставим туда невозможное значение — `10, 11, -1, -1`. В каждом контексте, впрочем, невозможные значения разные, поэтому по итогу null в этом протоколе можно сказать следующими способами: 0, -1, -999, 2005-01-01 00:00:00.0, 2023-12-31 23:59:59.999999 (с нетерпением жду наступающего нового года), xxx, x, ***, ALL, ***, %2A%2A%2A , null, nul — из-за того, что парсер один, чаще всего любым из них вне зависимости от контекста %)

Потом появились многомерные массивы/объекты. И что же они сделали? Решение элементарное: берём CSV вложенного объекта, делаем ему urlencode, вкладываем в CSV родительского, повторяем до посинения.

Прочих чудес уже и не упомню, но потом мне попалась игра на более старой версии движка... Там вместо запятых в CSV была строка del, во всех строковых значениях на всякий случай делалась подстановка dd0 ee0, а многомерные массивы кодировались удваиванием разделителя. То есть [1,2,3] будет 1del2del3del, а `[[1,2], [3,4]]` уже 1deldel2deldeldel3deldel4deldeldel. После таких приколов вопрос "а нафига потом это всё жмётся в gzip и переводится в base64" уже не стоял :-)

Простите, а что, JSON (под ручку с XML) уже не повсеместно распостранен? Что-то новое появилося и стало стандартом? Это только я так сильно отстал от современных технологий :)

Так я же и пишу — до тех времён, когда он стал повсеместным :-) Самое начало нулевых примерно.

CSV вообще удобен и в разборе и в генерации, grep, top, tail, excel - все прекрасно с ним

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

csv, json lines - единственные универсальные форматы работы с данными. Любой инженер, разраб даже из консоли с ними сможет практически в любой среде поработать, сделать выборку, даже поискать в данных перед загрузкой и что ему надо сделать. Все остальное - просто не так удобно.

а ведь xslt это текстовый xml, пожатый zip-ом

Вы точно уверены? Не перепутали с xlsx? :)

да ошибся, имел в виду экселевский формат с 2010 года xlsx

Ну так потому оно и быстрее. Т.к. обработка всех этих экранирований и сожрет всю эффективность.

Насчёт mdb: до какой-то поры это правда было очень удобно, пока не перешли на Win10 и .NET 5+. Поприседали с драйверами и решили, что таки лучше будет sqlite + MSSQL Server. Для совместимости со старыми программами DBF. А mdb для легаси остался (именно как база данных)

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

Человек сравнивает скорость работы кода на расте с библиотеками для джаваскрипта и питона))

Не скажу за раст и джаваскрипт, а написанная на C++ программа по обработке текста, будучи написана даже не то чтобы криво, а, скажем так, "наивно", может запросто проигрывать плюс-минус аналогичной программе, так же "наивно" написанной на Питоне. А если библиотека не "pure python", то и вообще нечему удивляться.

Именно поэтому большинство популярных библиотек для питона написано на C.

не, ну популярные библиотеки пишутся профи. А криво написать на С можно легко. Постоянный аллокейт/деаллокейт на каждую строчку и вот уже даже js будет работать быстрее

Видел на Хаскеле (на Хаскеле, Карл!) Для скорости там есть специальные строковые библиотеки, но человек не заморочился и взял дефолтные строки, которые в Хаскеле сделаны, не помню точно, как связные списки? Видимо, думал, будет быстрее - компилируется жо!

Я думаю что для этого придется разработать адаптировать код action Release Please на Rust, это следующий шаг)

Я, кажется, начинаю понимать, почему работодатели выстроили Великую Стену для соискателей на рынке труда...

Скомпилированный бинарник быстрее, чем простыня на py/js? Вот ведь неожиданность-то.

Xlsx весит 250 кбайт...

Множим на 10.000, получается 10 гигов, или 18-20 секунд тупо на ввод-вывод

Или тупо на то чтобы файлик лежал в одном из кэшей.

Начните с десятка файлов по 2-10MB, с графиками, формулами и UTF-16.

Разумеется, библиотека не идеальная.

"Программа работает, быстрее всех, но неправильно". Все "конкуренты" давно нащупали самые очевидные проблемы и обрабатывают их.

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

получается 10 гигов, или 18-20 секунд тупо на ввод-вывод

Чтобы не измерять IO (который, вообще-то, совсем не такой предсказуемый как вам кажется, ОС может его кэшировать), можно, например, читать из tmpfs (/tmp), а писать в /dev/null.

Дальше я нагуглил библиотеку calamine, и тупо из примеров разработчика взял кусок кода.

И какой процент именно вашего труда в итоговом решении? А то пока что всё это выглядит как нескучные обои.

нескучные обои и непременная статья о них...

нескучные обои

А мне «неонка» и «думатель» вспомнились

 в США сначала идёт месяц, а потом день, у нас же сначала день, а потом месяц. И "01-02-2024" они прочитают не как 1 февраля 24го, а как 2 января. И у меня нет идей, как решать такое. А какие у Вас есть мысли?

Если происхождение файла неизвестно - то перед записью пробежаться по таким строчкам и попробовать понять - в каком из этих 2 двухзначных чисел появляются числа более 12.... - то это скорее всего дата, оставшаяся - месяц. Ну правда тут есть вероятность нарваться на выгрузку с 01-12 числа - тут уж не поймешь. Так-что формат даты лучше указывать руками

Ну за оптимизм лайк. Но слишком много громких слов.

Во-первых, ты, судя по всему, написал не библиотеку, а скрипт. Слово «библиотека», согласен, звучит солидно, но этой солидности обычно и соответствовать надо.

Во-вторых, ты слишком рано начал писать статьи на Хабр. Нет, законом не запрещено, делай что хочешь, просто обычно люди тут ожидают прочесть нечто стоящее. Тем более под таким заголовком. Ты же описал опыт вдохновленного человека, который неделю назад прикоснулся к прелестям программирования и смог заставить работать хоть что-то. Я к тому, что для таких громких заголовков и слов ты, как я вижу, пока еще знаешь недостаточно. Ты в будущем поймешь, если продолжишь этим заниматься, насколько смешно выглядит «у меня не получилось заставить это работать на винде, поэтому я просто свичнулся на линукс». Чел... Или «вот вам бинарник на гитхабе». Чел... Ну и это еще не говоря о том, что реальные библиотеки делают в миллиарды больше работы и предоставляют для работы космическое количество умножить на миллиард функций больше, чем твой скрипт, работая при этом всего лишь в каких-то 33 раза медленнее (и к этому замеру у меня вообще вопросы, если честно).

В-третьих, не хочу быть причастным к убийству твоего энтузиазма и оптимизма, но просто надо понимать — все намного, намного сложнее, чем ты думаешь. Мира, братан.

ну 50/50 - человек выложил свой опыт ходьбы по граблям (наверное восторженная статья "как я это преодолел").... Таким же первопроходцам он ой-как пригодится.... Со стороны более опытных товарищей - как раз были бы интересны комментарии - "туда не ходи - это не так, сюда не ходи - это не так (и в идеале - с обоснованием, а не ПАТАМУЧТО). Мы все учимся на своих ошибках, стремление показать процесс - приветствуется, стремление показать процесс с ошибками, их преодолением и образовательной базой - идеально....

человек выложил свой опыт ходьбы по граблям

До греблей он ещё не дошёл, упал где-то в самом начале.

Спасибо за грамотные слова. К сожалению, хабровчане решили опустить рейтинг, так что могу достаточно редко комментировать.
Насчёт во-первых, я с тобой полностью согласен.
Насчёт во-вторых.

  1. Я действительно знаю недостаточно. Однако смог сделать то, что другие почему-то не сделали. Это больше всего удивило меня. Не в смысле что я смог, а в смысле, что никто другой таким не занялся.

  2. у меня не получилось заставить это работать на винде, поэтому я просто свичнулся на линукс Я не смог запустить из-за ошибки, касательно которого завёл Issue. Разработчик ответил, что исправит это в следующем билде =) Посоветовал использовать cargo clean, но мне не помогло даже пересоздание проекта с нуля.
    Что бинарник на гитхабе - мой косяк. Впрочем, вот эти ребята тоже бинарники не в релиз выложили, а к ним вопросов никаких или эти. В течение ближайшего времени (как только доделаю порт на питон) стуктурирую.
    А касательно количества работ библиотек - одна из библиотек для сравнения была xlsx2csv (на питоне (Вот эта)), и единственное, что она делает - превращает xlsx в csv. Да, возможностей предоставляет больше, в частности, можно выбирать название листа. Однако после небольшого допила это сможет и моя работа, что не должно вообще никак сказаться на производительности. И она работала в моих тестах даже медленнее, чем "общая" библиотека xlsx для typescript. И да, мне известно, что TypeScript сам по себе работает быстрее питона. Интересно будет посмотреть замеры библиотеки в питоне, как только доделаю.
    Насчёт замеров согласен, они не были выполнены в лабораторных условиях. Но тут погрешность даже в 100% не изменит вывода - моя xlsx2csv самая быстрая в мире для Typescript. . Кстати, Вы хорошо ли знаете питон и раст? Если да, можете помочь?

Я действительно знаю недостаточно. Однако смог сделать то, что другие почему-то не сделали. Это больше всего удивило меня. Не в смысле что я смог, а в смысле, что никто другой таким не занялся.

Другие понимают что им нужно. И то, что сделал ты - просто никому не нужно, либо есть другие способы, более качественные, как ускорить процессы.

Опять же, мало того что ты взял чужой код и постоянно говоришь "моя, моя", что уже всем не нравится, поскольку ты ее не писал, и даже не понимаешь как работает.
Так даже после того как тебе сказали в чем проблема, ты все равно продолжаешь считать это событие чем-то необыкновенным.

Другие понимают что им нужно. И то, что сделал ты - просто никому не нужно, либо есть другие способы, более качественные, как ускорить процессы.

Хм... прошу прощения, но Вы гуглить умеете? Потому как я секунд за 10 нашёл вот такой Issue

Firstly, I've also worked with openpyxl and it just works, but I've found that it's very slow for me and sometimes very inefficient.

Кроме того, моя честно украденная работа создана не под питон, а под TypeScript, где тот же Polars вообще не поддерживает чтение из Excel. Необходимо сначала конвертировать в csv, и только после этого работать. Конвертировать надо, естественно, сторонними методами, которые не быстрее, чем xlsx2csv или openpyxl.

Вы понимаете значение слова "natively"? Это когда вы можете взять ваш "TypeScript" скопировать в браузер и он будет работать. У вас же в зависимостях бинарные библиотеки, а соответственно он никак не сможет работать в браузере и мало чем отличается от подхода "просто запустить консольную утилиту с аргументами".

Хм... прошу прощения, но Вы гуглить умеете? Потому как я секунд за 10 нашёл вот такой Issue

Это не совсем issue, человек пишет что его не устраивал перформанс, поэотму он начал делать свой проект. А ему ответили, что в принципе их перформанс их устраивает, потому что они не так часто работают с эксель и уж точно не работают с эксель где сотня тысяч строк. Обычные люди к этому моменту переезжают в базы данных.
Ну и написали, чот если он будет свой проект развивать, продолжать и добавить в официальный репозиторий, то его движок могут добавить в поларис.

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

Ясно. Кстати, вот что мне написали разработчики поларса - что им идея показалась, скажем так, интересной. Ну, ждём реализации)

Но тут погрешность даже в 100% не изменит вывода - моя xlsx2csv самая быстрая в мире для Typescript. . Кстати, Вы хорошо ли знаете питон и раст? Если да, можете помочь?

Только не для TypeScript, а для NodeJS. А нету их, скорее всего, по тому что на сервере проще сконвертировать файл через консольную утилиту наподобии этой чем тащить в ноду еще один пакет на 3 строчки кода.

Только что проверил - скорости работы этой самой утилиты как раз как у xlsx2csv. Кроме того, для того, чтобы такую утилиту установить на сервер, нужны рут-права, для моей же честно украденной работы это не обязательно

Зачем ей root? Это такой же бинарник как у вас на github.

Да, Вы правы, технически, можно установить и запустить и без рута. Но тогда давайте посмотрим на список зависимостей

The following additional packages will be installed:
gnumeric-common gnumeric-doc libgoffice-0.10-10 libgoffice-0.10-10-common libgsf-1-114 libgsf-1-common
libjavascriptcoregtk-4.1-0 libmanette-0.2-0 libwebkit2gtk-4.1-0 libwpe-1.0-1 libwpebackend-fdo-1.0-1 libyelp0
pxlib1 xdg-dbus-proxy yelp yelp-xsl
Suggested packages:
gnumeric-plugins-extra libgsf-1-dev gstreamer1.0-alsa
The following NEW packages will be installed:
gnumeric gnumeric-common gnumeric-doc libgoffice-0.10-10 libgoffice-0.10-10-common libgsf-1-114 libgsf-1-common
libjavascriptcoregtk-4.1-0 libmanette-0.2-0 libwebkit2gtk-4.1-0 libwpe-1.0-1 libwpebackend-fdo-1.0-1 libyelp0
pxlib1 xdg-dbus-proxy yelp yelp-xsl
0 upgraded, 17 newly installed, 0 to remove and 28 not upgraded.
Need to get 50,4 MB of archives.
After this operation, 162 MB of additional disk space will be used.
17 пакетов =) Каждый из которых надо будет скачать ручками, установить и ничего не сломать. Кстати, прямо сейчас попробую установить такое без рут-прав, интересно, сможет ли линукс создать зависимости без рут-прав и утилиты dpkg?

Что же, это оказался не просто бинарник. Он ссылается на собственные сишные библиотеки, которые надо как минимум в path запихивать. А таких пакетов там 17.

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

Совершенно не спорю с этим. Более того, ваш подход к решению может быть весьма интересным. Критика вашей статьи же заключается совершенно в другом, в том что содержание статьи во многом не соответствует действительности. А именно:

  • Вы утверждаете, что это библиотека, хотя ничего общего с библиотекой это не имеет и, в отличии от той же утилиты выше, не является production ready.

  • Создаете впечатление, будто это утилита на чистом JavaScript/TypeScript, хотя на самом деле это обертка для кода на Rust.

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

Сам подход достаточно интересный и может быть действительно полезным, но я бы на вашем месте назвал статью, например: "Как Rust помог значительно ускорить NodeJS" и сделал бы акцент именно на использовании Node-API в Rust и как это можно использовать в своих приложениях с другими библиотеками на Rust. Думаю, что тогда бы рейтинг статьи был бы весьма в плюсе :)

Ну, сравнения с конкурентами я приводил.

Результаты: около 330 файлов у xlsx и около 280 у xlsx2csv. Получается, моя библиотека примерно в 33 раза быстрее, чем у конкурентов =)

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

Дорогой Кракотау,
я поздравляю вас со статьёй на хабре. Вы уже обнаружили, что тут не стесняются критиковать новичков (благо в основном по делу) и минусить статью/карму.

Не воспринимайте минусы и критику эмоционально, учитывайте, что в РФ и некоторых странах северной Европы сложилась такая культура жёсткой обратной связи.
В этой культуре считают, что лучше честная, пусть и жёсткая обратная связь (которая к сожалению может скатываться даже до оскорблений), чем английская/американская привычка хвалить любые самостоятельные попытки новичков в стиле "отличная работа, парень", но при этом за вашей спиной босс может сказать "что за отстой он написал, увольте этого парня побыстрее".

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

Комментарии как всегда довольно токсичные, но в целом по делу.

Никакой магии в программировании нет, если у вас что-то работает в 33 раз быстрее, то скорее всего либо у вас специфичная задача (и можно выкинуть разные проверки/краевые случаи), либо не оптимально используете чужие библиотеки, либо бенчмарк некорректный, либо у конкурентов специфичная платформа и они там не могут развернутся. Просто так на ровном месте сделать что-то быстрее довольно сложно, особенно в такой часто встречаемой задаче

Похоже на баг: публикация для Пикабу появилась на Хабре

xlsx2csv/Typescript/src/lib.rs (55 строк) - это и есть ваша библиотека? Серьезно? ;)

Это называется не библиотека, а пакет как left-pad?

Для дат рекомендую использовать следующий формат: 2023-11-03 23:55:59.345 +0

В этом формате все всем становится понятно. Даже в какой таймзоне отображена дата.

Касаемо даты в Excel... Дата хранится в числовом формате, поэтому неудивительно, что в csv экспортируется число. Нужно различать фактическое значение и отображаемое, к-рое зависит от формата ячейки. Фактическое значение хранится в Cell.Value, а отображаемое - в Cell.Text.

А́ в качестве разделителя можно использовать TAB (09). Внутри ячейки он практически не используется.

Спасибо за целую статью! Очень удобная штука - screenfetch. К сожалению, больше для себя тут ничего не нашёл.

Ничего суперского ты конечно не совершил) я когда-то самый быстрый конвертер UserEntity в UserDto написал)

Но пуканы ты знатно подожжешь, настоящий программист, должен долго и натужно настраивать чужую библиотеку странными костылями, а потом её постоянно чинить, а не написать свою тупую и примитивную в 55 строк

НЛО прилетело и опубликовало эту надпись здесь

он этими 55 строками как раз использовал чужую

И у него чужая либа работает в 33 раза быстрее, чем эта же чужая либа, но у него же? Правильно? ;)

НЛО прилетело и опубликовало эту надпись здесь

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

НЛО прилетело и опубликовало эту надпись здесь

И он решил, что это не автор либы, а он такой молодец? ;)

))) так ещё хитрее)

Юзнуть чужую, а сказать сам сделал.

Выбор, казалось бы, очевиден - пандас. Вещь мощная, но есть у неё проблема - очень медленная. На то, чтобы открыть xlsx файл размером 600 кбайт, ничего с ним не делая, уходит порядка 0.2 секунды.

Pandas не просто открывает библиотеку, ничего не делая. Он читает файл в память, раскладывая его в своем внутренним формате, которые упрощает и ускоряет запросы к данным. То есть фактически он конвертирует из XLSX в свой формат.

Пользователей ожидается 200 штук, и вопрос - сколько времени уйдёт у бота, чтобы обработать их одновременно?

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

Дальше я нагуглил библиотеку calamine, и тупо из примеров разработчика взял кусок кода. ... Ну, на этом разработка как бы всё. Теперь самое вкусное - тесты.

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

Почему я считаю мою библиотеку, вероятно, самой быстрой в мире?

Из-за огромного самомнения и примерно нулевого понимания своих действий?

Разумеется, библиотека не идеальная.

Здесь вообще нет вашей библиотеки.

Но стоило переключиться с Windows на Ubuntu, как всё прошло. Магия.

Когда ничего не знаешь, кругом столько чудес.

Вы слишком добры 😆

"Вероятно, не программист"?
"Вероятно, библиотеку"?
"Вероятно, написал"?
"Вероятно, самую быструю"?

Да

А какой результат по скорости выдаёт openpyxl в режиме read-only?
Помню, было неидеально, но достаточно шустро и работало из коробки.
Давайте ваш тестовый файл, протестируем.

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

А позже можно похвастать коллеге на обеде, что сделал новую оптимизацию на 20-30% быстрее.

НЛО прилетело и опубликовало эту надпись здесь

Вспомнил такой случай: поставило нам задачу руководство ускорить проект (на сервере), чтобы сэкономить мощности. Мои объяснения, что быстрее уже нельзя - физически железо не вытягивает, всё и там оптимизировано максимально - не принимались. Подключили к проблеме сис. админа. Объясняю ему: вот столько-то мегабайт текста программа выбрасывает в браузер, если посчитать - всё оптимально, процессор быстрее просто не может его генерировать. На что сис. админ присылает мне прогу на html/js, где генерируется гигантского размера строка и подсчитывается время генерации и оно оказывается реально очень маленьким. Я, помнится, опешил. Оказалось, что интерпретатор js очень умный и тупо выкидывал весь код генерации строки, т.к. она дальше никак не использовалась :) Но сис. админ, да, умный был :)

Чем умный?

Новичку удобно сортировать и анализировать в excel тогда, когда он плохо умеет в Google Colab пользоваться инструментами визуализации. Формат CSV нужен для хранения таблиц в формате текста и хорошо обрабатывается в любой среде. Наверное ещё есть плюсы этой библиотеки.

Добавлю про SATA SSD итд. Повторные чтения могли кэшироваться итд. Сделайте RAM-диск и на нем производите чтение и запись данных. Используйте лучше меньшее кол-во, НО больших файлов, чтобы устранить влияние файловых api ОС.

Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации