Diskussion zum Artikel "Die Arbeit mit ZIP-Archiven in MQL5 ohne Bibliotheken von Drittanbietern" - Seite 9

 
Forester #:
Ich habe fast 300 Dateien heruntergeladen und entpackt. Und die Daten darin werden immer größer und haben die Größengrenze erreicht.
Die Datei sollte 1,8 Milliarden Elemente haben, aber sie ist auf 1,5 Milliarden gekürzt. Einige Daten sind verloren gegangen. Es ist seltsam, dass sie so kurz ist, Arrays können bis zu 2147483647 Elemente haben.

Ich habe die (entpackten) Dateien herausgesucht, die ein bestimmtes Volumen überschreiten (für verschiedene Dateien von 1,7 GB bis 2136507776 - d. h. fast bis MAX_INT=2147483647, und Arrays können nicht mehr Elemente haben) und die bei der Ausgabe abgeschnitten werden. Es stellt sich heraus, dass sie alle als fehlerhaft markiert sind:

CryptDecode(CRYPT_ARCH_ZIP, m_file_puck, key, file_array);

D.h. Ausgabewert = 0.
Aber CZIP kontrolliert dies nicht. Ich habe die Größe des Ausgabe-Arrays auf Null gesetzt.
So kann ich in meinen Funktionen mit 100%iger Garantie feststellen, dass die Datei erfolgreich entpackt ist.
Vorher habe ich das korrekte Ende der JSON-Datei überprüft - aber diese Lösung ist nicht universell, und es scheint, dass mehrere Dateien von ~1000 versehentlich durch eine Zwischenzeile abgeschnitten wurden und als erfolgreich dekomprimiert akzeptiert wurden, aber die Daten darin sind nicht vollständig.

Neue Version der Funktion:

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);}//Größe auf 0 zurücksetzen
   }
   else
   {
      ArrayCopy(file_array, m_file_puck);
   }
}

Die neue istgelb hervorgehoben.

Vielleicht sollten die Entwickler auch das Array auf Null zurücksetzen, denn die abgeschnittenen Daten werden kaum von jemandem benötigt. Und sie können zu schwer erkennbaren Fehlern führen.

 
Forester #:

Ich habe die Dateien (entpackt) aussortiert, die ein bestimmtes Volumen überschreiten (für verschiedene Dateien von 1.7Gb bis 2136507776 - d.h. fast bis MAX_INT=2147483647, und Arrays können nicht mehr Elemente haben) und die bei der Ausgabe abgeschnitten werden. Es stellte sich heraus, dass alle von ihnen als fehlerhaft markiert wurden:

D.h. Ausgabewert = 0.
Aber CZIP kontrolliert das nicht. Ich habe die Größe des Ausgabe-Arrays auf Null gesetzt.
So kann ich in meinen Funktionen mit 100%iger Sicherheit feststellen, dass die Datei erfolgreich entpackt ist.
Vorher habe ich das korrekte Ende der JSON-Datei überprüft - aber diese Lösung ist nicht universell, und es scheint, dass mehrere Dateien von ~1000 versehentlich durch eine Zwischenzeile abgeschnitten wurden und als erfolgreich dekomprimiert akzeptiert wurden, aber die Daten in ihnen sind nicht vollständig.

Neue Version der Funktion:

Die neue istgelb hervorgehoben.

Vielleicht sollten die Entwickler auch das Array auf Null zurücksetzen, denn die abgeschnittenen Daten werden kaum von jemandem benötigt. Und sie können zu schwer erkennbaren Fehlern führen.

Erstens ist der Rückgabewert 0 kein 100%iges Fehlerzeichen (dies ist wahrscheinlich ein Überbleibsel aus der Zeit, als die Funktion nur zur Verschlüsselung, nicht aber zur Komprimierung verwendet wurde - es sollte wahrscheinlich geändert werden, aber es ist unwahrscheinlich, dass sie dies tun, um die Abwärtskompatibilität nicht zu beschädigen) für das Entpacken von zip, da zip rein technisch gesehen erlaubt, leere Daten zu archivieren ("receiver array" wird legitimerweise leer sein, ohne jeden Fehler).

Zweitens kann das Vorhandensein von teilweise entpackten Daten für die Fehlerdiagnose nützlich sein, und daher ist es besser, sie zu belassen.

 
Stanislav Korotky #:

Erstens ist ein Rückgabewert von 0 nicht zu 100% ein Hinweis auf einen Fehler

Bei meinen ~1000 Dateien konnte ich mit dem Label mit 0 - alle Dateien verwerfen, die ich nach dem Dateiendungsmuster durchsucht habe (d.h. es hat zu 100% funktioniert), und weitere 5 Stücke, die offensichtlich vom Zeilenende abgeschnitten waren.
Es ist also zuverlässiger als meine Methode.

Zweitens kann das Vorhandensein von teilweise entpackten Daten für die Fehlerdiagnose nützlich sein, und deshalb ist es besser, sie zu belassen.

In meinem Fall sind etwa 5 abgeschnittene Dateien übrig geblieben, die auf die gleiche Weise endeten wie das erwartete Ende der Datei und die auf keine andere Weise überprüft werden können - d.h. es handelt sich nicht um eine Fehlerdiagnose, sondern um ein Überspringen von Fehlern im Arbeitsalgorithmus.
Ihre Möglichkeiten der Fehlerdiagnose?

Allerdings habe ich die Frage für mich gelöst. Aber die Fehler wurden übersprungen, bis ich den Code von jemand anderem herausgefunden habe. Wenn es eine Nullstellung auf der MT-Seite gäbe, wären sie nicht da.

Im Allgemeinen gibt es Argumente dafür und dagegen. Die Entwickler werden entscheiden, was besser/logischer ist.

PS. Sie können -1 für Zip-Fehler mit einer Datei der Länge 0 hinzufügen.
 
Forester #:

In meinem Fall gibt es nur etwa 5 abgeschnittene Dateien, die genau wie das erwartete Ende der Datei enden und in keiner Weise mehr überprüft werden können - d.h. es handelt sich nicht um eine Fehlerdiagnose, sondern um Fehlerüberspringung im Arbeitsalgorithmus.

Welche Möglichkeiten der Fehlerdiagnose haben Sie?

Ich habe die Frage allerdings für mich gelöst. Aber die Fehler wurden übersprungen, bis ich den Code von jemand anderem herausgefunden habe. Wenn es einen Reset auf der MT-Seite gäbe, wären sie nicht da.

Ich habe nicht verstanden, wie Fehler übersprungen werden können. Die Funktion gab nicht Null und ein gefülltes Array mit teilweise fehlenden Daten aus dem Archiv zurück? Dann ist dies ein Fehler in MQL5 - es sollte dort korrigiert werden.

Wurde das _LastError-Flag überprüft?

Das "erwartete Ende der Datei" sollte nie gesetzt werden, da die Archivierung eine allgemeine Angelegenheit ist - wir kennen möglicherweise das Format der empfangenen Datei nicht.

 
Stanislav Korotky #:

Mir war nicht klar, wie viele Fehler übersehen werden konnten.

Dies ist ein Fehler in der CZIP-Bibliothek aus dem Artikel. Es gab keine Überprüfung des Ergebnisses des Entpackens. Es war nur

CryptDecode(CRYPT_ARCH_ZIP, m_file_puck, key, file_array);

Erst heute habe ich dies gefunden und die gelb markierte Prüfung hinzugefügt.

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);}//Größe auf 0 zurücksetzen

Zu Beginn der Verwendung war mir nicht klar, dass es keine Prüfung gab - deshalb habe ich meine Prüfung für das erwartete Ende der Datei erfunden.

Das "erwartete Ende der Datei" sollte nie festgelegt werden, da die Archivierung eine allgemeine Angelegenheit ist - wir kennen das Format der Datei, die wir erhalten, möglicherweise nicht.

Ich stimme zu, deshalb habe ich das Array im Falle eines Fehlers auf Null gesetzt.
Das ist die universellste Sache, die man tun kann, außer für den Fall, dass die Datei 0 groß ist.
Aber auch mit 0-ter Dateigröße werde ich JSON nicht verarbeiten/parsen und niemand wird es tun - nur Schleifen über Elemente werden nicht gestartet, wenn die Anzahl der Elemente=0 ist, also ist das Nullsetzen des Arrays meiner Meinung nach eine gute Lösung.

 
Beigefügt ist eine kleine Änderung des Bibliothekscodes für die neuen Realitäten (b5223+) von MQL5.
Новая версия платформы MetaTrader 5 build 5200: расширение OpenBLAS и усиление контроля в MQL5
Новая версия платформы MetaTrader 5 build 5200: расширение OpenBLAS и усиление контроля в MQL5
  • 2025.08.20
  • www.mql5.com
В пятницу 1 августа 2025 года будет выпущена обновленная версия платформы MetaTrader 5...
Dateien:
ZipHeader.mqh  27 kb
 
Forester #:

Ich bin auf ein Archiv gestoßen, das CZip nicht dekomprimieren konnte. Gleichzeitig dekomprimieren 7ZIP und Windows archiver ohne Probleme.
druckte die Größe der komprimierten Daten aus - es stellte sich heraus, dass sie einige zehn Megabyte kleiner ist als das Archiv (und es ist nur eine Datei darin).

Ich begann zu suchen, wo die Größe berechnet wird, und fand sie in der Funktion FindZipFileSize().

Experimentiert...
Es stellte sich heraus, dass das Archiv korrekt entpackt wird, wenn man alle end_size-Daten als Datengröße zurückgibt. Offenbar bestimmt der Code beim Entpacken selbst das Ende der Daten, anstatt sich auf die Antwort dieser Funktion zu verlassen. Die Hauptsache ist, dass sie nicht kleiner sein sollte. Man könnte es so lassen, aber es stellt sich heraus, dass die Funktion nutzlos ist, was unwahrscheinlich ist. Und vielleicht scheitern auch andere Archive...
Ein weiteres Experiment hat gezeigt, dass, wenn man die Zeilen auskommentiert

Das Archiv beginnt auch zu entpacken. Die Datenmenge liegt nahe bei 100%.

Es stellt sich heraus, dass das Archiv uint cdheader = 0x504b0102; hat, und dies ist ein Teil der komprimierten Daten, nicht eine Kennzeichnung des Endes.

Haben Sie einen Fehler bei der Kennzeichnung gemacht? Ich habe ein solches Label bei der Internetsuche gefunden. Vielleicht sollte es auf andere Weise verarbeitet werden, anstatt die Daten damit zu schneiden, habe ich 30 MB abgeschnitten.

Funktioniert mit dieser Datei: (Datei \Include\Zip\Zip.mqh).

Ich kann Ihnen die Archivdatei in einer privaten Nachricht schicken, wenn Sie daran interessiert sind, es herauszufinden.

Die Sache ist die, dass es ein Format Zip gibt, das genau geregelt und beschrieben ist, und es gibt verschiedene Packer (Windows, Total Commander, 7zip, etc.), die auf diesem Standard aufsetzen und jeweils sehr kreativ beim Ausfüllen von Headerstrukturen sind. CZip kann sich also nicht darauf verlassen, dass das Format korrekt ausgefüllt wird, und errechnet selbst, was es kann. Was da mit dem Bezeichner 0x504b0102 steht, muss geklärt werden.

Wir sollten den Code noch einmal überarbeiten und ein funktionierendes Update herausbringen, das Ihre wertvollen Kommentare berücksichtigt. Ich bin froh, dass jemand die Lib benutzt.

 
fxsaber #:
Beigefügt ist eine kleine Änderung des Bibliothekscodes für die neuen Realitäten (b5223+) von MQL5.

Vielen Dank dafür. MQL5 ist mehr und mehr sinnlos und rücksichtslos.

99% der Fehler hätten vermieden werden können, wenn MetaQuotes endlich Standardreflexions- und Serialisierungsfunktionen implementiert hätte.

 
Forester #:

Ich bin auf ein Archiv gestoßen, das CZip nicht entpacken konnte. 7ZIP und das Windows-Archivierungsprogramm entpackten es jedoch ohne Probleme.

...

Ich kann Ihnen die Archivdatei in einer privaten Nachricht schicken, wenn Sie daran interessiert sind, sie zu verstehen.

Bitte senden Sie mir die Archivdatei in einer privaten Nachricht zu.

 
Vasiliy Sokolov #:

Bitte senden Sie mir die Archivdatei in einer privaten Nachricht.

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

hier im Archivkörper (nicht im Header) steht cdheader = 0x504b0102;

Auch in der nächsten Datei nach Datum. Ich denke, es wird oft gefunden.

header = 0x504b0304; steht in jeder Datei im Header, also den ersten 4 Zeichen.
Aber es kommt auch vor und im Body des Archivs, selten. Ich werde jetzt danach suchen.

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


Ich denke, es ist notwendig, für diese Header nur zwischen den Körpern der Archive zu suchen.