Обсуждение статьи "Работаем с ZIP-архивами средствами MQL5 без использования сторонних библиотек" - страница 9

 
Forester #:
Скачал и распаковал почти 300 файлов. А данных в них все больше и достиг предела по размеру.
Файл должен быть с 1,8 млрд char элементов, а распаковывается обрезанным до 1,5 млрд. Часть данных теряется. Странно, что так коротко обрезается, массивы могут иметь до 2147483647 элементов.

Разобрался с файлами (распакованными) превышающими некий объем (для разных файлов от 1,7Гб до 2136507776 - т.е. почти до MAX_INT=2147483647, а массивы не могут иметь больше элементов) и которые на выходе получаются обрезанными. Оказалось, что все они отмечены, как ошибочные при:

CryptDecode(CRYPT_ARCH_ZIP, m_file_puck, key, file_array);

Т.е. выходное значение = 0.
Но CZIP это не контролирует. Сделал обнуление размера выходного массива.
Так в моих функциям могу со 100% гарантией определять, что файл успешно распакован.
До этого проверял правильный конец JSON файла }\r\n - но это решение не универсально и кажется несколько файлов из ~1000 были случайно обрезаны по промежуточной строке и были приняты. как успешно распакованные, но в них данные - не полные.

Новый вариант функции:

void CZipFile::GetUnpackFile(uchar &file_array[])
{
   static const uchar key[] = {1, 0, 0, 0};
   if(m_header.comp_method)
   {
      int dSize=CryptDecode(CRYPT_ARCH_ZIP, m_file_puck, key, file_array);
      if(dSize==0){Print("Err in CriptDecode. Arr size: ",ArraySize(file_array));ArrayResize(file_array,0);}//reset size to 0
   }
   else
   {
      ArrayCopy(file_array, m_file_puck);
   }
}

Желтым выделено новое.

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

 
Forester #:

Разобрался с файлами (распакованными) превышающими некий объем (для разных файлов от 1,7Гб до 2136507776 - т.е. почти до MAX_INT=2147483647, а массивы не могут иметь больше элементов) и которые на выходе получаются обрезанными. Оказалось, что все они отмечены, как ошибочные при:

Т.е. выходное значение = 0.
Но CZIP это не контролирует. Сделал обнуление размера выходного массива.
Так в моих функциям могу со 100% гарантией определять, что файл успешно распакован.
До этого проверял правильный конец JSON файла }\r\n - но это решение не универсально и кажется несколько файлов из ~1000 были случайно обрезаны по промежуточной строке и были приняты. как успешно распакованные, но в них данные - не полные.

Новый вариант функции:

Желтым выделено новое.

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

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

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

 
Stanislav Korotky #:

Во-первых, возвращаемое значение 0 не является 100% признаком ошибки

С моими ~1000 файлами метка с 0 - позволила отбросить все файлы, которые я искал по шаблону конца файла (т.е. сработало на 100%) и еще штук 5, которые видимо по концу строки были обрезаны.
Так что это надежнее, чем мой способ.

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

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

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

В общем есть аргументы за и против. Разработчики решат что лучше/логичнее.

ПС. Можно -1 добавить для ошибки с zip, при файле 0-й длины.
 
Forester #:

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

Ваши варианты диагностики ошибок?

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

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

Флаг _LastError проверялся?

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

 
Stanislav Korotky #:

Я не понял, как ошибки могли пропускаться. 

Это недоработка библиотеки CZIP из статьи. Проверка на результат распаковки не производилась. Было просто

CryptDecode(CRYPT_ARCH_ZIP, m_file_puck, key, file_array);

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

int dSize=CryptDecode(CRYPT_ARCH_ZIP, m_file_puck, key, file_array);
if(dSize==0){Print("Err in CriptDecode. Arr size: ",ArraySize(file_array));ArrayResize(file_array,0);}//reset size to 0

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

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

Согласен, потому и сделал обнуление массива при ошибке.
Это самое универсальное, что можно сделать, кроме случая с 0-м размером файла.
Но и при 0-м файле я и обрабатывать/разбирать JSON не буду и никто не будет - просто циклы по элементам не будут запускаться, если число элементов=0, так что обнуление массива, на мой взгляд - хорошее решение.

 
В приложении небольшая доработка кода библиотеки под новые реалии (b5223+) MQL5.
Новая версия платформы MetaTrader 5 build 5200: расширение OpenBLAS и усиление контроля в MQL5
Новая версия платформы MetaTrader 5 build 5200: расширение OpenBLAS и усиление контроля в MQL5
  • 2025.08.20
  • www.mql5.com
В пятницу 1 августа 2025 года будет выпущена обновленная версия платформы MetaTrader 5...
Файлы:
ZipHeader.mqh  27 kb
 
Forester #:

Встретился архив, который CZip не смог распаковать. При этом 7ZIP и архиватор Винды распаковывают без проблем.
Распечатал размер сжатых данных - оказалось на десятки мегабайт меньше архива (а в нем только 1 файл).

Начал искать где он расчитывается, и нашел в функции FindZipFileSize().

Поэкспериментировал...
Оказалось что если вернуть, как размер данных все данные end_size - то архив распаковывается правильно. Видимо при распаковке код сам определяет конец данных, а не полагается на ответ из этой функции. Главное, чтобы не было меньше.  Можно было оставить так, но получается, что функция бесполезна, а это вряд ли. И возможно какие-то другие архивы будут сбоить..
Еще 1 эксперимент показал, что если закоментировать строки

То архив тоже начинает распаковываться. Количество данных приблизилось к 100%

Получается, что в архиве имеется  uint cdheader =   0x504b0102; и это часть сжатых данных, а не метка их конца.

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

Рабочая с этим файлом функция: (файл \Include\Zip\Zip.mqh)

Файл архива могу скинуть в личку, если есть интерес разобраться.

Дело в том, что есть формат Zip, который точно регламентирован и описан, а есть различные упаковщики (windows, total commander, 7zip и т.д.), которые болт забили на этот стандарт и каждый очень творчески подходит к заполнению структур-заголовков. Поэтому CZip не может полагаться на корректно правильный заполненный формат, и рассчитывает что можно самостоятельно. Что там с идентификатором 0x504b0102 надо разбираться.

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

 
fxsaber #:
В приложении небольшая доработка кода библиотеки под новые реалии (b5223+) MQL5.

Спасибо. MQL5 все бессмысленней и беспощадней.

99% ошибок удалось бы избежать, если бы MetaQuotes наконец-то внедрила бы штатные функции рефлексии и сериализации.

 
Forester #:

Встретился архив, который CZip не смог распаковать. При этом 7ZIP и архиватор Винды распаковывают без проблем.

...

Файл архива могу скинуть в личку, если есть интерес разобраться.

Скиньте пожалуйста файл архива мне в личку.

 
Vasiliy Sokolov #:

Скиньте пожалуйста файл архива мне в личку.

https://quote-saver.bycsi.com/orderbook/linear/BTCUSDT/2023-01-18_BTCUSDT_ob500.data.zip

тут в теле архива (не в заголовке) присутствует cdheader =   0x504b0102;

В следующем по дате файле тоже. Думаю часто встречается.

header =     0x504b0304; есть в каждом файле именно в заголовке, т.е. первые 4 символа.
Но он же встречался и в теле архива, редко. Сейчас поищу.

Тут https://quote-saver.bycsi.com/orderbook/linear/BTCUSDT/2023-03-15_BTCUSDT_ob500.data.zip


Думаю надо поиск этих заголовков делать только между телами архивов.