Discussão do artigo "Manipulação de Arquivos ZIP em Linguagem MQL5 Pura" - página 9

 
Forester #:
Baixei e descompactei quase 300 arquivos. E os dados contidos neles estão ficando maiores e atingiram o limite de tamanho.
O arquivo deveria ter 1,8 bilhão de elementos char, mas foi descompactado e cortado para 1,5 bilhão. Alguns dados foram perdidos. É estranho que ele tenha sido cortado tão curto, pois as matrizes podem ter até 2147483647 elementos.

Classifiquei os arquivos (descompactados) que excedem um determinado volume (para arquivos diferentes, de 1,7 GB a 2136507776 - ou seja, quase até MAX_INT=2147483647, e as matrizes não podem ter mais elementos) e que são cortados na saída. Acontece que todos eles estão marcados como errôneos em:

CryptDecode(CRYPT_ARCH_ZIP, m_file_puck, key, file_array);

Ou seja, valor de saída = 0.
Mas o CZIP não controla isso. Eu zerei o tamanho da matriz de saída.
Assim, em minhas funções, posso determinar com 100% de garantia que o arquivo foi descompactado com êxito.
Antes disso, eu verificava o final correto do arquivo JSON }\r\n - mas essa solução não é universal e parece que vários arquivos de ~1000 foram acidentalmente cortados por uma linha intermediária e foram aceitos como descompactados com sucesso, mas os dados neles não estão completos.

Nova versão da função:

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);}//redefine o tamanho para 0
   }
   else
   {
      ArrayCopy(file_array, m_file_puck);
   }
}

A nova versão está destacada emamarelo .

Talvez os desenvolvedores devessem também zerar a matriz, pois os dados cortados não são necessários para ninguém. E podem levar a erros difíceis de ver.

 
Forester #:

Classifiquei os arquivos (descompactados) que excederam um determinado volume (para arquivos diferentes, de 1,7 Gb a 2136507776 - ou seja, quase até MAX_INT=2147483647, e as matrizes não podem ter mais elementos) e que foram cortados na saída. Descobriu-se que todos eles foram marcados como errôneos em:

Ou seja, valor de saída = 0.
Mas o CZIP não controla isso. Eu zerei o tamanho da matriz de saída.
Assim, em minhas funções, posso determinar com 100% de garantia que o arquivo foi descompactado com êxito.
Antes disso, verifiquei o final correto do arquivo JSON }\r\n - mas essa solução não é universal e parece que vários arquivos de ~1000 foram acidentalmente cortados por uma linha intermediária e foram aceitos como descompactados com sucesso, mas os dados neles não estão completos.

Nova versão da função:

A nova versão está destacadaem amarelo .

Talvez os desenvolvedores devessem também zerar a matriz, pois os dados cortados não são necessários para ninguém. E podem levar a erros difíceis de ver.

Em primeiro lugar, o valor de retorno 0 não é um sinal de erro de 100% (isso provavelmente é remanescente da época em que a função era usada apenas para criptografia, mas não para compactação - provavelmente deveria ser alterado, mas é improvável que o façam, para não prejudicar a compatibilidade com versões anteriores) para descompactar o zip, porque o zip tecnicamente permite arquivar dados vazios ("array do receptor" estará vazio legitimamente, sem nenhum erro).

Em segundo lugar, a presença de dados parcialmente descompactados pode ser útil para o diagnóstico de erros e, portanto, é melhor deixá-los.

 
Stanislav Korotky #:

Em primeiro lugar, um valor de retorno de 0 não é 100% indicativo de um erro

Com meus ~1000 arquivos, o rótulo com 0 - me permitiu descartar todos os arquivos que pesquisei pelo padrão de fim de arquivo (ou seja, funcionou 100%) e outros 5 pedaços que aparentemente foram cortados pelo fim da linha.
Portanto, é mais confiável do que o meu método.

Em segundo lugar, a presença de dados parcialmente descompactados pode ser útil para diagnosticar erros e, portanto, é melhor deixá-los.

No meu caso, restam cerca de 5 arquivos cortados, que terminaram da mesma forma que o final esperado do arquivo e que não podem ser verificados de nenhuma outra maneira - ou seja, isso não é um diagnóstico de erro, mas um erro de ignorar no algoritmo de trabalho.
Suas opções de diagnóstico de erro?

No entanto, resolvi a questão por mim mesmo. Mas os erros foram ignorados até eu descobrir o código de outra pessoa. Se houvesse zeragem no lado do MT, eles não estariam lá.

Em geral, há argumentos a favor e contra. Os desenvolvedores decidirão o que é melhor/lógico.

PS. Você pode adicionar -1 para erro de zip com arquivo de comprimento 0.
 
Forester #:

No meu caso, há apenas cerca de 5 arquivos cortados que terminaram exatamente como o final esperado do arquivo e que não podem mais ser verificados de forma alguma - ou seja, não se trata de diagnóstico de erro, mas de omissão de erro no algoritmo de trabalho.

Quais são suas opções para o diagnóstico de erros?

No entanto, resolvi a questão por mim mesmo. Mas os erros foram ignorados até eu descobrir o código de outra pessoa. Se houvesse uma reinicialização no lado do MT, eles não estariam lá.

Eu não entendia como os erros podiam ser ignorados. A função retornou não zero e uma matriz preenchida com dados parcialmente ausentes do arquivo? Então, esse é um erro na MQL5, que deve ser corrigido lá.

O sinalizador _LastError foi verificado?

O "expected end of file" (fim esperado do arquivo) nunca deve ser definido, porque o arquivamento é algo generalizado - podemos não saber o formato do arquivo recebido.

 
Stanislav Korotky #:

Não me dei conta de como os erros poderiam ter sido perdidos.

Essa é uma falha na biblioteca CZIP do artigo. Não houve verificação do resultado da descompactação. Era apenas

CryptDecode(CRYPT_ARCH_ZIP, m_file_puck, key, file_array);

Hoje mesmo encontrei isso e adicionei essa verificação destacada em amarelo.

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);}//redefine o tamanho para 0

No início do uso, não percebi que não havia nenhuma verificação - por isso inventei minha verificação para o final esperado do arquivo.

O "fim esperado do arquivo" nunca deve ser definido, pois o arquivamento é algo generalizado - talvez não saibamos o formato do arquivo que estamos recebendo.

Concordo, e é por isso que zerei a matriz em caso de erro.
Essa é a coisa mais universal que pode ser feita, exceto no caso de tamanho de arquivo 0.
Mas mesmo com o tamanho de arquivo 0, eu não processarei/analisarei o JSON e ninguém o fará - apenas os loops nos elementos não serão iniciados se o número de elementos for 0, portanto, zerar a matriz, na minha opinião, é uma boa solução.

 
Em anexo, há uma pequena modificação no código da biblioteca para as novas realidades (b5223+) da MQL5.
Новая версия платформы MetaTrader 5 build 5200: расширение OpenBLAS и усиление контроля в MQL5
Новая версия платформы MetaTrader 5 build 5200: расширение OpenBLAS и усиление контроля в MQL5
  • 2025.08.20
  • www.mql5.com
В пятницу 1 августа 2025 года будет выпущена обновленная версия платформы MetaTrader 5...
Arquivos anexados:
ZipHeader.mqh  27 kb
 
Forester #:

Deparei-me com um arquivo que o CZip não conseguiu descompactar. Ao mesmo tempo, o 7ZIP e o Windows Archiver descompactaram sem problemas.
Imprimi o tamanho dos dados compactados, que acabou sendo dezenas de megabytes menor do que o arquivo (e há apenas um arquivo nele).

Comecei a procurar onde ele é calculado e o encontrei na função FindZipFileSize().

Experimentei...
Descobri que, se você retornar todos os dados end_size como tamanho dos dados, o arquivo será descompactado corretamente. Aparentemente, ao descompactar, o próprio código determina o fim dos dados, em vez de confiar na resposta dessa função. O principal é que ele não deve ser menor. Você poderia deixá-lo assim, mas acontece que a função é inútil, o que é improvável. E talvez alguns outros arquivos falhem...
Mais um experimento mostrou que, se você comentar as linhas

O arquivo também começa a ser descompactado. A quantidade de dados está próxima de 100%.

Acontece que o arquivo tem uint cdheader = 0x504b0102; e isso é uma parte dos dados compactados, não um rótulo de seu final.

Você cometeu algum erro com o rótulo? Encontrei esse rótulo em uma pesquisa na Internet. Talvez devesse ser processado de outra forma, em vez de cortar dados por ele, cortei 30 MB.

Função trabalhando com este arquivo: (arquivo \Include\Zip\Zip.mqh).

Posso lhe enviar o arquivo em uma mensagem privada, caso tenha interesse em descobrir.

O problema é que existe um formato Zip, que é precisamente regulado e descrito, e há vários empacotadores (windows, total commander, 7zip etc.) que se baseiam nesse padrão e cada um deles é muito criativo no preenchimento das estruturas de cabeçalho. Portanto, o CZip não pode confiar que o formato seja preenchido corretamente e calcula o que pode por conta própria. O que está lá com o identificador 0x504b0102 deve ser resolvido.

Devemos revisar o código novamente e lançar uma atualização funcional que leve em conta seus valiosos comentários. Fico feliz que alguém esteja usando a biblioteca.

 
fxsaber #:
Em anexo, há uma pequena modificação no código da biblioteca para as novas realidades (b5223+) da MQL5.

Obrigado. A MQL5 está cada vez mais sem sentido e implacável.

99% dos erros poderiam ter sido evitados se a MetaQuotes tivesse finalmente implementado funções padrão de reflexão e serialização.

 
Forester #:

Deparei-me com um arquivo que o CZip não conseguiu descompactar. No entanto, o 7ZIP e o arquivador do Windows o descompactaram sem problemas.

...

Posso enviar o arquivo para você em uma mensagem privada se estiver interessado em entendê-lo.

Envie o arquivo para mim em uma mensagem privada.

 
Vasiliy Sokolov #:

Envie-me o arquivo em uma mensagem privada.

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

Aqui, no corpo do arquivo (não no cabeçalho), há cdheader = 0x504b0102;

No arquivo next by date também. Acho que ele é encontrado com frequência.

header = 0x504b0304; está em todos os arquivos no cabeçalho, ou seja, nos primeiros 4 caracteres.
Mas ele também é encontrado no corpo do arquivo, raramente. Vou procurá-lo agora.

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


Acho que é necessário procurar esses cabeçalhos somente entre os corpos dos arquivos.