====== Archiv — ZIP, TAR, RAR, ISO ====== Vier Units für Archiv- und Abbildformate, alle vollständig in Lyx umgesetzt. Externe Bibliotheken braucht keine davon; einzige Abhängigkeit ist ''std.zlib'' für die DEFLATE-Kompression in ''std.zip''. → [[lyx_-_programmiersprache:units|Standard Library]] · [[lyx_-_programmiersprache:units:gzip|std.gzip]] · [[lyx_-_programmiersprache:units:zlib|std.zlib]] Alle Beispiele dieser Seite sind mit ''lyxc 1.0.21A'' übersetzt und ausgeführt; die gezeigten Ausgaben sind echte Programmausgaben. Die erzeugten Archive wurden zusätzlich mit ''unzip'', ''tar'' und ''7z'' gegengelesen. ---- ===== Die vier Units ===== ^ Unit ^ Lesen ^ Schreiben ^ Kompression ^ Beschreibung ^ | [[lyx_-_programmiersprache:units:zip|std.zip]] | ja | ja | DEFLATE (automatisch) | ZIP nach PKWARE APPNOTE; bis 4096 Einträge, kein ZIP64, kein Passwort | | [[lyx_-_programmiersprache:units:tar|std.tar]] | ja | ja | keine | POSIX ustar; für ''.tar.gz'' mit [[lyx_-_programmiersprache:units:gzip|std.gzip]] kombinieren | | [[lyx_-_programmiersprache:units:rar|std.rar]] | **nur stored** | nein | keine | RAR5-Reader; komprimierte Einträge sind unsichtbar (proprietärer Algorithmus) | | [[lyx_-_programmiersprache:units:iso|std.iso]] | ja | ja | keine | ISO 9660 Level 1; Reader läuft den ganzen Verzeichnisbaum ab, Writer erzeugt ein flaches Wurzelverzeichnis | ===== Welches Format wofür ===== ^ Aufgabe ^ Empfehlung ^ Warum ^ | Dateien austauschen | ''std.zip'' | überall lesbar, komprimiert automatisch | | Sicherung oder Auslieferungspaket | ''std.tar'' + ''std.gzip'' | Rechte und Pfade bleiben erhalten, Kompression getrennt wählbar | | Viele kleine Dateien bündeln, Größe egal | ''std.tar'' | kein Kompressionsaufwand, einfachstes Format | | Bootfähiges CD-, DVD- oder USB-Abbild | ''std.iso'' | einziges Format der vier mit Abbild-Charakter | | Fremdes ISO-Abbild auslesen | ''std.iso'' | Reader kennt Unterverzeichnisse | | Vorhandenes RAR-Archiv lesen | ''std.rar'' | nur wenn die Einträge //stored// sind — sonst gar nicht | | RAR erzeugen | **geht nicht** | ''std.rar'' hat keinen Writer; ''std.zip'' nehmen | ---- ===== Ein Muster für alle ===== Die vier Units teilen sich dieselbe Handle-Schnittstelle. Wer eine kennt, kennt alle: Lesen Schreiben Open(pfad) → Handle WriterNew() → Handle Count(h) → Anzahl WriterAdd(h, name, daten, laenge) Name(h, idx) → Zeiger WriterSave(h, pfad) → 0 = ok Size(h, idx) → Bytes WriterFree(h) Find(h, name) → Index oder -1 Read(h, idx, puffer, max) → Bytes Close(h) Die Präfixe sind ''Zip'', ''Tar'', ''Rar'' und ''Iso'' — ''ZipCount'', ''TarCount'', ''RarCount'', ''IsoCount''. Einzige Abweichung: ''std.zip'' nennt die Größenabfrage ''ZipUncompSize'' (nicht ''ZipSize''), weil im Archiv zusätzlich die komprimierte Größe steht. ''std.rar'' hat nur die linke Spalte. import std.zip; import std.tar; import std.iso; import std.alloc; import std.string; // Dasselbe Muster fuer alle drei Schreiber fn main(): int64 { var z: int64 := ZipWriterNew(); ZipWriterAdd(z, "README.txt"c, "Hallo aus Lyx!"c as int64, 14); PrintLn(StrConcat("ZIP gespeichert, rc = ", IntToStr(ZipWriterSave(z, "/tmp/demo.zip"c)))); ZipWriterFree(z); var t: int64 := TarWriterNew(); TarWriterAdd(t, "daten/log.txt"c, "Zeile 1\nZeile 2\n"c as int64, 16); PrintLn(StrConcat("TAR gespeichert, rc = ", IntToStr(TarWriterSave(t, "/tmp/demo.tar"c)))); TarWriterFree(t); var i: int64 := IsoWriterNew(); IsoWriterAdd(i, "README.TXT"c, "ISO 9660 aus Lyx"c as int64, 16); PrintLn(StrConcat("ISO gespeichert, rc = ", IntToStr(IsoWriterSave(i, "/tmp/demo.iso"c)))); IsoWriterFree(i); // Und wieder lesen - ebenfalls dasselbe Muster var h: int64 := ZipOpen("/tmp/demo.zip"c); var idx: int64 := ZipFind(h, "README.txt"c); var buf: int64 := alloc(256); var n: int64 := ZipRead(h, idx, buf, 256); poke8(buf + n, 0); PrintLn(StrConcat(StrConcat("ZIP Eintraege: ", IntToStr(ZipCount(h))), StrConcat(" README.txt = ", buf as pchar))); ZipClose(h); return 0; } ZIP gespeichert, rc = 0 TAR gespeichert, rc = 0 ISO gespeichert, rc = 0 ZIP Eintraege: 1 README.txt = Hallo aus Lyx! Die drei Dateien sind mit den üblichen Werkzeugen lesbar: $ unzip -l /tmp/demo.zip 14 2017-01-01 00:00 README.txt $ tar -tf /tmp/demo.tar daten/log.txt $ 7z l /tmp/demo.iso ..... 16 16 README.TXT ---- ===== Pfadangaben und Rückgabewerte ===== Zwei Stolperstellen, die sich durch alle vier Units ziehen: * **''std.zip'' erwartet Pfade als Adresse** (''%%"datei.zip"c as int64%%''), ''std.tar'', ''std.rar'' und ''std.iso'' als ''pchar'' (''%%"datei.tar"c%%''). Der Unterschied stammt aus #1264 und ist an den Signaturen der Einzelseiten ablesbar. * **''…WriterSave'' liefert ''0'' bei Erfolg** (der jeweilige ''…_ERR_OK''-Wert), ''…Open'' dagegen ''0'' im **Fehlerfall** und sonst ein Handle. Wer beide Rückgaben gleich behandelt, prüft eine davon falsch herum. Ebenfalls für alle vier gleich: * ''Name()'' liefert einen **internen** Zeiger — nie freigeben, nach ''Close()'' nicht mehr benutzen. * ''Read()'' schreibt in einen Puffer, den der Aufrufer selbst anlegt, und **terminiert nicht**. Für die Textausgabe hinter den gelesenen Bytes selbst ein Nullbyte setzen. * ''Find()'' vergleicht den **vollständigen** Namen einschließlich Verzeichnisanteil (''daten/log.txt''), nicht nur den Dateinamen. * Das Archiv liegt beim Lesen vollständig im Speicher; streamenden Zugriff gibt es bei keiner der Units. ---- ===== Grenzen im Überblick ===== ^ ^ std.zip ^ std.tar ^ std.rar ^ std.iso ^ | Einträge | 4096 | 4096 | 4096 | 4096 | | Namenslänge | Archivgrenze | **100 Byte** | 511 Byte | 8.3 vorgesehen | | Verzeichnisse | im Namen | im Namen | im Namen (lesend) | **flach beim Schreiben** | | Zeitstempel | fest 2017-01-01 | 0 (1970) | gelesen, nicht ausgewertet | Erstellzeit im Abbild | | Kompression | DEFLATE ab 65 Byte | keine | keine | keine | Drei dieser Grenzen führen zu **stillem** Verhalten und sind auf den Einzelseiten belegt: * **TAR schneidet zu lange Pfade ab.** Ein 110 Zeichen langer Pfad wird ohne Fehlermeldung auf 100 Zeichen gekürzt — GNU tar liest anschließend den gekürzten Namen. * **ISO normalisiert Namen.** ''EinLangerName.txt'' wird zu ''EINLANGERNAME.TXT'', und ''unterordner/a.txt'' zu ''UNTERORDNER_A.TXT'' — der Schrägstrich wird ersetzt, ein Unterverzeichnis entsteht nicht. * **RAR verschweigt komprimierte Einträge.** ''RarCount'' zählt sie nicht mit; ein Archiv kann „leer" wirken, obwohl ''7z l'' Dateien anzeigt. ---- ===== Und die Kompression? ===== ''std.zip'' bringt DEFLATE selbst mit (über ''std.zlib'') und entscheidet je Eintrag: bis 64 Byte //stored//, darüber komprimiert. Die anderen drei Formate komprimieren nicht — dafür gibt es eigene Units: ^ Unit ^ Aufgabe ^ | [[lyx_-_programmiersprache:units:gzip|std.gzip]] | gzip-Ströme lesen und schreiben — die zweite Hälfte von ''.tar.gz'' | | [[lyx_-_programmiersprache:units:zlib|std.zlib]] | DEFLATE/Inflate und die zlib-Hülle, dazu Adler-32 und CRC-32 | ---- **Weiterführend:** [[lyx_-_programmiersprache:units:zip|std.zip]] · [[lyx_-_programmiersprache:units:tar|std.tar]] · [[lyx_-_programmiersprache:units:rar|std.rar]] · [[lyx_-_programmiersprache:units:iso|std.iso]] · [[lyx_-_programmiersprache:guides:iso|Guide: ISO-Abbilder]] Letzte Aktualisierung: 2026-08-13 — Schnellstart durch ein lauffähiges Programm ersetzt (die drei alten Ausschnitte waren nie übersetzt worden) und um den Gegenlesetest mit ''unzip''/''tar''/''7z'' ergänzt. Neu: Format-Wahl mit Begründung, Grenzen-Vergleich der vier Units, die drei still wirkenden Grenzen und der Hinweis auf die uneinheitliche Pfad-Übergabe. Die Seite [[lyx_-_programmiersprache:units:rar|std.rar]] ist neu angelegt — sie war hier verlinkt, existierte aber nicht. Codebeispiele geprüft: gegen **lyxc 1.2.5C** übersetzt (Prüflauf 2026-09-08 über die gesamte Doku: 574 Vollprogramme, 0 echte Fehler; zusätzlich 5159 Aufrufe gegen die ''pub fn''-Signaturen in ''aurum/std'' gehalten, 0 Abweichungen).