Обсуждение статьи "Работаем с ZIP-архивами средствами MQL5 без использования сторонних библиотек" - страница 8
Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
Планируется ли добавление функции распаковки строки, сжатой алгоритмом GZIP?
Краткий ответ: нет, не планируется, так как это совсем другой формат не совместимый с zip. Для работы с GZip нужна отдельная, аналогичная этой, библиотека. Далее моя цитата из соседней ветки:
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
WebSocket и GZIP
Vasiliy Sokolov, 2024.03.21 14:35
Стоит различать форматы хранения данных от алгоритмов сжатия.
Zip - это формат хранения нескольких файлов в одном, наподобии формата TAR. Сами файлы в формате zip обычнно сжимаются алгоритмом сжатия deflate, но могут не сжиматся им вовсе, а просто хранится в этом формате, в таком случае формат позволяет просто объединить несколько файлов в один архив (файл) без сжатия.
GZip это формат хранения сжатых данных алгоритмом deflate в одном файле.
Если Вам выдали GZip - формат zip вам не подойдет. Вам нужно знать формат gzip и распоковать его с помощью системной функции CryptEncode(CRYPT_ARCH_ZIP). Это не сложно сделать самостоятельно, без привлечения сторонних библиотек, так как алгоритм сжатия там один и тот же, deflate (в MQL он имеет не очень удачный идентификатор CRYPT_ARCH_ZIP). Жаль что нет специальной статьи "Работаем с GZip архивом средствами MQL5". В целом, это не задача системной функции, а задача специальной MQL бибилотеки, оборачивающий deflate вокруг формата gzip.
Есть какие-нибудь новости по этому вопросу? Я сталкиваюсь с ошибками
Якоби, Станислав Короткий опубликовал пакет, содержащий эту библиотеку zip, здесь, с некоторыми исправлениями.
Я протестировал его, и пока что он работает довольно хорошо.
Встретился архив, который CZip не смог распаковать. При этом 7ZIP и архиватор Винды распаковывают без проблем.
Распечатал размер сжатых данных - оказалось на десятки мегабайт меньше архива (а в нем только 1 файл).
CompressedSize:76964920Начал искать где он расчитывается, и нашел в функции FindZipFileSize().Поэкспериментировал...
Оказалось что если вернуть, как размер данных все данные end_size - то архив распаковывается правильно. Видимо при распаковке код сам определяет конец данных, а не полагается на ответ из этой функции. Главное, чтобы не было меньше. Можно было оставить так, но получается, что функция бесполезна, а это вряд ли. И возможно какие-то другие архивы будут сбоить..
Еще 1 эксперимент показал, что если закоментировать строки
То архив тоже начинает распаковываться. Количество данных приблизилось к 100%
CompressedSize:106638447Получается, что в архиве имеется uint cdheader = 0x504b0102; и это часть сжатых данных, а не метка их конца.Вы не ошиблись с меткой? В интеренте поиском нашел такую метку. Может ее как то по другому надо обрабатывать, а не обрезать данные по ней, у меня обрезалось 30МБ.
Файл архива могу скинуть в личку, если есть интерес разобраться.Рабочая с этим файлом функция: (файл \Include\Zip\Zip.mqh)
С очередным файлом ошибка. На этот раз помогло комментирование строк
Т.е. код uint header = 0x504b0304; тоже встречается в содержимом архива и он успешно распаковывается 7Zip, Windows и этой исправленной версией CZip.
Т.к. оба выхода из цикла отключены, то и цикл стал лишним, его можно удалить и возвращать:
В этой функции явно какая то недоработка. Ведь и условие
никогда не исполнится, т.к. при выходе из цикла по достижении конца данных, будет size == end_size, а не на 1 меньше.
В итоге функцию укоротил до одной строки:
Программа с этой версией функции уже скачала 110 архивов на 12 Гг в сумме и всё успешно распаковала.
Если у кого будут проблемы с распаковкой - можете попробовать такой вариант функции.
Файл должен быть с 1,8 млрд char элементов, а распаковывается обрезанным до 1,5 млрд. Часть данных теряется. Странно, что так коротко обрезается, массивы могут иметь до 2147483647 элементов.
Обрезанные данные выдает терминальная функция
С этим уже ничего не сделаешь...
Подумал, что можно ровными к кб/мб блоками декодировать - подавал 1024, 1024*1024 и 1024*1024*10 - не получилось.
Может как то Виндовый архиватор можно использовать? Через WinExec распаковать в файл, потом его построчно читать. Так автоматизация останется. Но не для маркета.Придется не распаковывать на лету, а сохранять архивы, потом вручную распаковывать и уже потом их обрабатывать. Неудобно будет - без автоматизации ((
Может как то Виндовый архиватор можно использовать? Через WinExec распаковать в файл, потом его построчно читать.
Можно, это очевидно. А в чём проблема? Может я неправильно понял? Издавна есть консольные архиваторы UnRAR.exe, UnZip.exe и др.
С очередным файлом ошибка. На этот раз помогло комментирование строк
Т.е. код uint header = 0x504b0304; тоже встречается в содержимом архива и он успешно распаковывается 7Zip, Windows и этой исправленной версией CZip.
Т.к. оба выхода из цикла отключены, то и цикл стал лишним, его можно удалить и возвращать:
В этой функции явно какая то недоработка. Ведь и условие
никогда не исполнится, т.к. при выходе из цикла по достижении конца данных, будет size == end_size, а не на 1 меньше.
В итоге функцию укоротил до одной строки:
Программа с этой версией функции уже скачала 110 архивов на 12 Гг в сумме и всё успешно распаковала.
Если у кого будут проблемы с распаковкой - можете попробовать такой вариант функции.
Могу предположить, что метки все же нужно искать, но не в теле архива, а между файлами, если их несколько. Наверное должны быть где-то записаны длины архива...
В общем, мое решение частное под мою задачу с 1-м файлом в архиве, если их несколько - возможно нужно как-то по другому делать.
Могу предположить, что метки все же нужно искать, но не в теле архива, а между файлами, если их несколько. Наверное должны быть где-то записаны длины архива...
В общем, мое решение частное под мою задачу с 1-м файлом в архиве, если их несколько - возможно нужно как-то по другому делать.
Сделал распечатку сжатых и несжатых размеров которые должны быть в заголовках.
Те файлы, что я скачивал - имеют там 0 0. Если размер=0, то вызывается обсуждаемая выше FindZipFileSize()
Создал нормальным архиватором архив с 1-м файлом. Размеры в заголовке:
46389587 376516461
И еще архив с 2-мя файлами, включая тот, что был добавлен в первый архив:
46981880 314725045
46389587 376516461
Оба варианта имеют записанные в заголовках размеры и не вызывали FindZipFileSize()
А те файлы, что я скачивал (с 0 0 в размерах) - видимо создавались софтом, который не записал размеры в заголовки.Возможно, мое решение укоротить FindZipFileSize() универсальное.
Можно, это очевидно. А в чём проблема? Может я неправильно понял? Издавна есть консольные архиваторы UnRAR.exe, UnZip.exe и др.
Сделал распаковку через 7-zip (UnZip.exe c 2009г не обновлялся о поддержке даже Win 7 не написано).
Сравнил скорость:
Эта CZIP библиотека:
2025.06.14 20:59:06.758 Archive successfully opened. Total files: 1.
2025.06.14 20:59:07.345 UnZipped
587 мс
7-zip:
2025.06.14 21:00:07.312 Start unzip by 7-Zip.
2025.06.14 21:00:09.274 UnZipped by 7-Zip. File size: 428.22 MB
1962 мс
Это только на распаковку файла со сбросом на SSD диск. А еще надо читать файл с диска построчно.
Общее время от старта до окончания парсинга:
Total Time: 10s 709ms
и
Total Time: 12s 892ms
Разница 2 с 183 мс
В общем, для скорости предпочтительнее использовать эту CZIP библиотеку и если файл слишком большой, то использовать другие архиваторы.
Мне для ~1000 файлов по 2 сек = 33 минуты экономии. На самом деле больше, т.к. это пример с самым маленьким файлом на 428 мб, CZIP распаковывает файлы до ~1.7 Гб.
Все что больше (до 4 Гб) обрабатывает 7-zip. Так что 1-1.5 часа экономии есть.
Тестировал CZIP c моими правками - распаковал 600+ файлов на 100Гб без ошибок.