記事"MQL5でのZIPアーカイブの扱い"についてのディスカッション - ページ 9

 
Forester #:
300近いファイルをダウンロードして解凍した。そして、その中のデータはどんどん大きくなり、サイズ制限に達してしまった。ファイルには18億個の要素があるはずだが、解凍すると15億個になる。 いくつかのデータが失われている。配列は最大
2147483647 個の要素を持つことができる。 。

ある一定の容量(1.7GBから2136507776まで、つまりほぼMAX_INT=2147483647まで、配列はそれ以上の要素を持つことができない)を超えるファイル(アンパックされたもの)で、出力時にカットされるものを整理してみた。これらはすべて、出力時にエラーとしてマークされることがわかった:

CryptDecode(CRYPT_ARCH_ZIP, m_file_puck, key, file_array);


しかしCZIPはこれを制御できない。私は出力配列のサイズをゼロにした。
だから私の関数では、ファイルが正常に解凍されたかどうかを100%の保証で判断できる。
その前に、JSONファイルの末尾が正しいかどうかをチェックした。しかし、この解決策は万能ではなく、~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);}// サイズを0にリセット
   }
   else
   {
      ArrayCopy(file_array, m_file_puck);
   }
}

新しいものは黄色で ハイライトされている。

トリミングされたデータはほとんど誰にも必要とされないので、開発者は配列もゼロにリセットすべきかもしれない。そして、見えにくいエラーにつながるかもしれない。

 
Forester #:

ある容量(1.7Gbから2136507776まで、つまりほぼMAX_INT=2147483647まで、配列はそれ以上の要素を持つことができない)を超え、出力時にカットされるファイル(解凍済み)を整理した。その結果、これらすべてが出力時にエラーとしてマークされることが判明した:


しかしCZIPはこれを制御できない。私は出力配列のサイズをゼロにした。
だから私の関数では、ファイルが正常に解凍されたかどうかを100%の保証で判断できる。
その前に、JSONファイルの末尾が正しいかどうかをチェックした。しかし、この解決策は万能ではなく、~1000個のファイルのうち、いくつかのファイルが誤って中間行で切断され、正常に解凍されたものとして受け入れられたが、その中のデータは完全ではなかったようだ。

関数の新バージョン:

新しいものは黄色で ハイライトされている。

トリミングされたデータはほとんど誰にも必要とされないので、開発者は配列もゼロにリセットすべきかもしれない。そして、見えにくいエラーにつながるかもしれない。

なぜなら、zip は純粋に技術的に空のデータをアーカイブすることができるからである("receiver array" はエラーなしで正当に空になる)。

第二に、部分的に解凍されたデータの存在はエラー診断に有用であるため、残しておいたほうがよい。

 
Stanislav Korotky #:

第一に、戻り値0は100%エラーを示すものではありません。

私の~1000個のファイルでは、0 - のラベルで、ファイル末尾のパターンで検索したすべてのファイル(つまり100%うまくいった)と、行末で切り取られたらしい別の5個のファイルを破棄することができた。
だから、私のやり方より信頼できる。

第二に、部分的に解凍されたデータの存在は、エラーの診断に役立つかもしれないので、残しておいた方がいい。

私の場合、5つほどカットされたファイルが残っていますが、それらは予想されるファイルの終わり方と同じように終わっていて、他の方法ではチェックできません。つまり、これはエラー診断ではなく、作業アルゴリズムのエラースキップです。
エラー診断のオプションは?

しかし、私自身はこの疑問を解決しました。しかし、私が他の人のコードを理解するまで、エラーはスキップされていました。

一般的に、賛否両論がある。何がより良いのか/論理的なのかは、開発者が決めることだろう。

追記長さ0のファイルに対するzipエラーには-1を追加できる。
 
Forester #:

つまり、これはエラー診断ではなく、作業アルゴリズムにおけるエラースキップなのだ。

エラー診断にはどのような方法がありますか?

しかし、私自身はこの疑問を解決しました。しかし、私が他人のコードを理解するまで、エラーはスキップされていた。MT側にリセットがあれば、エラーは出ないはずだ。

どうしてエラーがスキップされるのか理解できなかった。この関数はゼロではなく、アーカイブから部分的に欠落したデータで満たされた配列を返しましたか?それならこれはMQL5のバグで、そこで修正されるべきです。

LastErrorフラグはチェックされましたか?

アーカイブは一般化されたものであるため、"expected end of file "を設定すべきではありません。

 
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);}// サイズを0にリセット

使い始めのころは、チェックがないことに気づかなかった。

アーカイブというのは一般化されたもので、受信したファイルのフォーマットがわからないことがあるからだ。

私もそう思います。だからこそ、エラーに備えて配列をゼロにするようにしたのです。
これは、ファイルサイズが0の場合を除けば、最も普遍的なことです。
しかし、ファイルサイズが0であっても、私はJSONを処理/パースしませんし、誰も処理しません。

 
MQL5の新しい現実(b5223+)の ために、ライブラリのコードを少し修正しました。
Новая версия платформы 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とWindowsアーカイバは問題なく解凍できた。
圧縮データのサイズをプリントアウトしたところ、アーカイブより数十メガバイト少なかった(しかも1ファイルしかない)。

私はそれがどこで計算されるのか探し始め、FindZipFileSize()関数でそれを見つけた。

実験してみたところ...
end_sizeのデータをすべてデータサイズとして返すと、アーカイブが正しく解凍されることがわかった。どうやら解凍時に、この関数からの応答に頼るのではなく、コード自身がデータの終わりを判断しているようだ。このままにしておいてもいいのだが、この関数が役に立たないことが判明した。そして、おそらく他のアーカイブも失敗するだろう...
もうひとつ実験したところ、以下の行をコメントアウトすると、このようになることがわかった。

アーカイブも解凍を始める。データ量は100%に近い。

このアーカイブにはuint cdheader =0x504b0102;があり、これは圧縮データの一部であって、末尾のラベルではないことがわかった。

ラベルを間違えたのでしょうか?インターネット検索でそのようなラベルを見つけました。

このファイル(㊟㊟㊟㊟㊟㊟㊟㊟㊟㊟㊟㊟㊟)で動いている関数です。

もし興味があれば、プライベートメッセージでアーカイブファイルを送ることができる。

問題は、Zipというフォーマットがあり、それは正確に規定され、記述されているということです。そして、様々なパッカー(windows、total commander、7zipなど)があり、それらはこの標準をボルトで固定し、それぞれがヘッダー構造を埋めるのに非常に独創的です。そのため、CZipはフォーマットが正しく埋められていることを信頼することができず、それ自身でできることを計算する。識別子0x504b0102 があるものは整理されなければならない。

私たちはもう一度コードを修正し、あなたの貴重なコメントを考慮したアップデートを行うべきです。このlibを使ってくれる人がいてうれしい。

 
fxsaber #:
MQL5の新しい現実(b5223+) 用のライブラリコードの小さな修正を添付します。

ありがとう。MQL5はますます無意味で冷酷になっています。

MetaQuotesが最終的に標準的なリフレクションとシリアライゼーション関数を 実装していれば、エラーの99%は回避できたはずです。

 
Forester #:

CZipが解凍できないアーカイブに出くわした。しかし、7ZIPとWindowsアーカイバは問題なく解凍できた。

...

もしご興味があれば、プライベートメッセージでアーカイブファイルをお送りします。

プライベートメッセージでアーカイブファイルを送ってください。

 
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 です。


これらのヘッダは、アーカイブ本体の間だけで探す必要があると思います。