![]() |
TZipfile - ModifiedDateTime unter Linux und MAC richtig auslesen
Um in einem bestehenden Zip-Archiv das Änderungsdatum einer Datei auszulesen mache ich es so:
Delphi-Quellcode:
Unter Windows wird mir das richtige Datum und Zeit zurückgegeben, unter macOS und Linux aber ein um ca. 7 Jahre zu altes Datum.
DatumZeitStr := FormatDateTime ('dd.mm.yyyy hh:nn:ss', FileDateToDateTime (Zipfile.FileInfo[c].ModifiedDateTime));
Könnt Ihr das bestätigen? Ist das ein Bug, oder muss für diese Plattformen irgend etwas anders gemacht werden? |
AW: TZipfile - ModifiedDateTime unter Linux und MAC falsch
Vermutlich hat es damit zu tun:
"The precise format of a time stamp depends on the OS" Das Zitat stammt aus dem Hilfetext zu System.SysUtils.FileDateToDateTime. Jetzt dürfte dein Zeitstempel evtl. im Format eines OS in die ZIP Datei gespeichert worden sein, was aber diese Funktion, wenn sie auf einer anderen Plattform ausgeführt wird nicht weiß. Die wird einfach vom Format der vorliegenden Plattform ausgehen. Man bräuchte da sowas wie eine Variante der man per Parameter noch mitgeben kann, für welche Plattform die Konvertierung durchgeführt werden soll. => QP Feature Request und Nummer hier posten, damit wir abstimmen können. Bis dahin: Quellcode der Funktion anschauen und sich selber eine solche Variante bauen. Man muss dazu dann aber wissen, ob der Zeitstempel in der ZIP-Datei immer im selben Format gespeichert ist oder wie man sonst das Format erkennt... Grüße TurboMagic |
AW: TZipfile - ModifiedDateTime unter Linux und MAC falsch
Im Mac die Zip ausgelesen und/oder auch dort erstellt?
Von Delphi erstellt, bzw. von Delphi gelesen, oder durch jemand Anderen? Wenn im Mac erstellt und dort auch gelsen, dann macht die Genauigkeit keine Jahre aus, sondern eher maximal Sekunden/Minuten. Aber in einer Zip wird das Datum und die Attribute nicht immer gleich gelspeichert, da die Hauseigenen Zip-Programme für diese Systeme auch die Eigenheiten der Dateisysteme einbeziehen. In Windows ist es standardmäßig im DOS-Format, aber es gibt optional auch erweiterte Infos, wo das Datum mit höherer Genauigkeit nochmal drin steht. Falls hier ein Mac-Programm die Zip erstellt hat und die Delphi-Komponente das immer versucht im Windows-Format zu lesen, dann passt das nicht mehr zusammen. Andersrum sollte es aber stimmen, da die ordentlichen Mac-Programme wissen, wenn die eine Windows-Zip lesen und es dann entsprechend auslesen/umschalten. |
AW: TZipfile - ModifiedDateTime unter Linux und MAC falsch
Es ist egal, mit welchem Programm oder auf welchem OS-System die ZIP-Datei erstellt wurde, TZIP-File gibt immer das falsche Datum und Uhrzeit zurück.
Zip-Dateien, die mit TZipl-File erstellt werden, werden aber von anderen Programmen richtig anzeigt (aber TZipfile zeigt die selbst erstellten auch falsch an). Also ist es ein Ausleseproblem. Da kommen einige Ansatzpunkte in Betracht: ModifiedDateTime ist als UNIT32 im TZipheader definiert:
Delphi-Quellcode:
Daher war eine erste Annahme, ob es etwas mit Integer-Problemen zu tun haben könnte, da auf den unterschiedlichen Plattformen einige Integertypen unterschiedliche Anzahl Bytes haben.
TZipHeader = packed record
MadeByVersion: UInt16; // Start of Central Header RequiredVersion: UInt16; // Start of Local Header Flag: UInt16; CompressionMethod: UInt16; ModifiedDateTime: UInt32; CRC32: UInt32; In der Procedure TZipFile.REadCentralHeader wird es dann so ausgelesen:
Delphi-Quellcode:
VerifyRead(FStream, LHeader.ModifiedDateTime, Sizeof(UInt32));
Ich habe nun festgestellt, dass auf allen Plattformen
Delphi-Quellcode:
Zipfile.FileInfo[c].ModifiedDateTime
den gleichen Wert zurückliefert, nur FileDateToDateTime liefert aber offenbar unterschiedliche Ergebnisse zurück. Für Linux / MAC ist FileDatetoDateTime wie wolgt definiert:
Delphi-Quellcode:
function FileDateToDateTime(FileDate: LongInt): TDateTime;
var TempFileDate: time_t; UT: tm; begin TempFileDate := FileDate; localtime_r(TempFileDate, UT); Result := EncodeDate(UT.tm_year + 1900, UT.tm_mon + 1, UT.tm_mday) + EncodeTime(UT.tm_hour, UT.tm_min, UT.tm_sec, 0); end; |
AW: TZipfile - ModifiedDateTime unter Linux und MAC falsch
![]() 4.3.7 Local file header 4.3.12 Central directory structure 4.4.6 date and time fields B.2 Field Code, Description > 0008, Modification Date Ja, Original steht das Datum in den beiden Header-Strukturen. (vor jedem Dateistream und als Dateiliste am Ende) Normal steht im Local-Header und Central-Structure das Selbe, außer die ZIP wurde sequentiell erstellt und beim Schreiben des LocalHeaders war dessen Inhalt noch nicht bekannt ... hier gilt dann nur das aus dem CentralHeader. Alternativ kann das Datum auch in den ExtraFields stehen ... dann gilt nur dieser Wert, je nach Format des ExtraFields. z.B. 4.5.5 -NTFS Extra Field (0x000a) > Mtime, 8 bytes, File last modification time oder 4.5.7 -UNIX Extra Field (0x000d) > Mtime, 4 bytes, File last modification time |
AW: TZipfile - ModifiedDateTime unter Linux und MAC falsch
OK, wie vermutet mal wieder diese schönen Integer-Spielchen:
Unter 32-Bit Plattformen und Windows 64 Bit Plattform ist Longint ein 4 Byte Typ, unter Linux 64 bit und mac 64 aber ein 8 Byte Typ. Da ich gerade nicht wüsste, wie ich in der System.Sysutils das anpassen könnte (wohl per IFDEF auch den Header der Funktion ändern), habe ich es als temporäre Lösung so gemacht, so funktioniert es dann auch unter allen Plattformen:
Delphi-Quellcode:
UInt32 ist immer ein 4 Byte-Type.
{$IFNDEF MSWindows}
function FileDateToDateTime(FileDate: UInt32): TDateTime; begin Result := EncodeDate( LongRec(FileDate).Hi shr 9 + 1980, LongRec(FileDate).Hi shr 5 and 15, LongRec(FileDate).Hi and 31) + EncodeTime( LongRec(FileDate).Lo shr 11, LongRec(FileDate).Lo shr 5 and 63, LongRec(FileDate).Lo and 31 shl 1, 0); end; {$ENDIF} Daher sollte man diese Änderung nur da verwenden, wo man ModifiedDateTime (=UINT32) verwendet, denn FileDateToDateTime (searchrec.time =LongInt) funktioniert unter Linux 64 und MacOS 64. |
AW: TZipfile - ModifiedDateTime unter Linux und MAC falsch
Hallo,
schön, dass du die Ursache und für dich einen Workaround gefunden hast. Da das so, wie du schreibst, nach einem Bug in TZipFile klingt solltest du den bitte aber auch in QP erfassen, damit alle eine Chance auf einen Fix haben. Die QP Nummer dann wie sicher schon bekannt hier posten... Grüße TurboMagic |
AW: TZipfile - ModifiedDateTime unter Linux und MAC falsch
Liste der Anhänge anzeigen (Anzahl: 2)
Ich würde das mal also eher nicht als BUG bezeichnen, sondern man muss halt diese Umstände kennen und entsprechend auf den Plattformen anders reagieren. Ich werde aber noch mal überlegen, ob das nicht irgendwie eleganter geht, durch einen intelligenten Typecast oder so.
Jedenfalls bin ich froh, dass es nun funktioniert, hatte mich schon über die Erweiterung "TZipFile.delete" in Delphi 11 gefreut, welches somit das entfernen und aktualisieren von Dateien im Zip-Archiv nun sehr viel einfacher macht. Nur brauche ich dafür natürlich das richtige Datum, um zu vergleichen, ob etwas aktualisiert werden muss. Gerade unter Linux war mir das wichtig, denn da vertreibe ich meine Programme immer als ZIP-Datei, das war bislang aber immer ein recht umständliches Management, da ich geänderte Programmdateien dann mit dem Linux-Zip-Programm ("Archivverwaltung") manuell in die speziell präparierte ZIP-Datei (mit Basis Verzeichnis "hastasoft") verschieben musste. Jetzt habe ich in mein Linux-Dateimanager-Programm File-IO einen Aktualisierungs-Dialog eingebaut (siehe Anlage), wo ich einfach die Zip-Datei auswähle und dann den Entwicklungsordner auf dem PC und mit einem Klick werden neue oder geänderte Dateien in das ZIP-Archiv übernommen... |
AW: TZipfile - ModifiedDateTime unter Linux und MAC falsch
Wieso soll das ein Fehler von TZipFile sein? Das Feld ModifiedDateTime steht als UInt32 im ZipHeader. Das Problem ist die Umwandlung über FileDateToDateTime und das hat gar nichts mit TZipFile zu tun.
Die Zip-Specs beschreiben diese vier Bytes folgendermaßen: Zitat:
Der beschriebene Workaround ist zwar funktionsfähig, sollte aber m.E. anders heißen und ohne damit IFNDEF Windows auskommen:
Delphi-Quellcode:
Ich glaube auch nicht, dass hier die unterschiedlichen Längen eines Longint die Ursache sind. Vielmehr wird bei Unix die Anzahl der Sekunden seit 1. Januar 1970, 00:00 Uhr UTC in dem Wert gespeichert, während bei der MS-DOS Version die einzelnen Datums- und Zeitanteile als Bits abgelegt sind (siehe
function ZipFileDateToDateTime(FileDate: UInt32): TDateTime;
begin Result := EncodeDate( LongRec(FileDate).Hi shr 9 + 1980, LongRec(FileDate).Hi shr 5 and 15, LongRec(FileDate).Hi and 31) + EncodeTime( LongRec(FileDate).Lo shr 11, LongRec(FileDate).Lo shr 5 and 63, LongRec(FileDate).Lo and 31 shl 1, 0); end; ![]() |
AW: TZipfile - ModifiedDateTime unter Linux und MAC falsch
Hallo Uwe,
du hast da natürlich recht. Die frage ist nur, ob so eine Umwandlungsroutine nicht irgendwo mitgeliefert werden sollte? Dann würden evtl. nicht noch andere in das Fettnäpfchen, dass die vom OP benutzte Routine zufällig unter Windows funktioniert tappen... Grüße TurboMagic |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:12 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz