====== std.rar — RAR5-Archive lesen ======
''std.rar'' liest Archive im **RAR5**-Format (Signatur ''Rar!\x1A\x07\x01\x00''). Die Unit ist ein reiner Reader ohne externe Abhängigkeiten: Sie zerlegt die Blockstruktur des Archivs und stellt die enthaltenen Dateien über dasselbe Handle-Muster bereit wie ''std.zip'' und ''std.tar''.
→ [[lyx_-_programmiersprache:units:archiv|Archiv-Übersicht]] · [[lyx_-_programmiersprache:units:zip|std.zip]] · [[lyx_-_programmiersprache:units:tar|std.tar]] · [[lyx_-_programmiersprache:units|Standard Library]]
Alle Beispiele dieser Seite sind mit ''lyxc 1.0.21A'' übersetzt und ausgeführt; die gezeigten Ausgaben sind echte Programmausgaben.
> **Nur unkomprimierte Einträge sind sichtbar.** Der RAR-Kompressionsalgorithmus ist proprietär und in ''std.rar'' nicht umgesetzt. Einträge mit einer anderen Methode als //stored// werden beim Öffnen **stillschweigend übersprungen** — sie erscheinen weder in ''RarCount'' noch über ''RarFind''. Da handelsübliche Packer standardmäßig komprimieren, sind die meisten RAR-Archive aus freier Wildbahn für diese Unit **leer**.
>
> Wer RAR nur lesen muss und die Archive selbst erzeugt: mit „Speichern"/„store" packen. Wer freie Wahl hat, nimmt [[lyx_-_programmiersprache:units:zip|std.zip]] oder [[lyx_-_programmiersprache:units:tar|std.tar]] — beide lesen **und** schreiben.
**Kein Writer.** RAR-Archive lassen sich mit ''std.rar'' nicht erzeugen; es gibt keine ''RarWriter*''-Funktionen.
----
===== Konstanten =====
^ Konstante ^ Wert ^ Bedeutung ^
| ''RAR_MAX_ENTRIES'' | 4096 | Höchstzahl erfasster Einträge |
| ''RAR_ERR_OK'' | 0 | kein Fehler |
| ''RAR_ERR_NOTRAR'' | 1 | keine gültige RAR5-Datei |
| ''RAR_ERR_IO'' | 2 | Datei nicht lesbar |
| ''RAR_ERR_CORRUPT'' | 3 | Archiv beschädigt |
| ''RAR_ERR_COMPRESSED'' | 4 | Eintrag ist komprimiert |
Die Fehlercodes sind für eigene Fehlerbehandlung gedacht: Die Funktionen selbst melden Fehler über ''0'' (kein Handle) beziehungsweise ''-1''.
----
===== Funktionen =====
^ Signatur ^ Rückgabe ^ Beschreibung ^
| ''RarOpen(path: pchar): int64'' | Handle oder ''0'' | Liest das Archiv vollständig in den Speicher und erfasst alle //stored//-Einträge. ''0'' bei fehlender Datei, zu kurzer Datei oder falscher Signatur. |
| ''RarClose(handle: int64): void'' | – | Gibt Rohdaten, Namen und Eintragstabelle frei. |
| ''RarCount(handle: int64): int64'' | Anzahl | Zahl der **erfassten** Einträge — komprimierte sind nicht dabei. |
| ''RarName(handle: int64, idx: int64): int64'' | Zeiger | Dateiname als nullterminierter Text. **Interner Puffer — nicht freigeben.** |
| ''RarSize(handle: int64, idx: int64): int64'' | Bytes | Größe der gespeicherten Daten. |
| ''RarRead(handle: int64, idx: int64, outBuf: int64, maxLen: int64): int64'' | gelesene Bytes | Kopiert die Daten in einen selbst angelegten Puffer, höchstens ''maxLen''. |
| ''RarFind(handle: int64, name: int64): int64'' | Index oder ''-1'' | Sucht einen Eintrag über den vollständigen Namen. |
''RarOpen'' erwartet den Pfad als ''pchar'' (seit #1264), die übrigen Funktionen arbeiten mit Adressen.
----
===== Beispiel =====
import std.rar;
import std.alloc;
import std.string;
fn main(): int64 {
var h: int64 := RarOpen("/tmp/lyx_test.rar"c);
if (h == 0) { PrintLn("kein RAR5-Archiv oder nicht lesbar"); return 1; }
PrintLn(StrConcat("stored-Eintraege: ", IntToStr(RarCount(h))));
var i: int64 := 0;
while (i < RarCount(h)) {
PrintLn(StrConcat(StrConcat(" ", RarName(h, i) as pchar),
StrConcat(" ", IntToStr(RarSize(h, i)))));
i := i + 1;
}
var idx: int64 := RarFind(h, "README.txt"c);
if (idx >= 0) {
var buf: int64 := alloc(256);
var n: int64 := RarRead(h, idx, buf, 256);
poke8(buf + n, 0);
PrintLn(StrConcat("Inhalt: ", buf as pchar));
}
RarClose(h);
return 0;
}
Gegen ein RAR5-Archiv mit zwei gespeicherten Dateien:
stored-Eintraege: 2
README.txt 14
daten/notiz.txt 13
Inhalt: Hallo aus Lyx!
Dasselbe Programm gegen ein Archiv, das eine gespeicherte **und** eine komprimierte Datei enthält:
stored-Eintraege: 1
stored.txt 13
''packed.txt'' fehlt — obwohl ''7z l'' beide Einträge auflistet. Genau das meint der Warnkasten oben.
----
===== Was der Reader vom Archiv liest =====
RAR5 besteht aus einer Signatur (8 Byte) und daran anschließenden Blöcken. Jeder Block beginnt mit CRC32 und Headergröße, danach folgen Typ und Flags als //vint// (7 Bit je Byte, oberstes Bit = „noch ein Byte").
^ Blocktyp ^ Wert ^ Behandlung ^
| MAIN | 1 | übersprungen |
| FILE | 2 | ausgewertet — siehe unten |
| ENDARC | 5 | beendet den Durchlauf |
| alle übrigen (SERVICE, CRYPT …) | – | übersprungen |
Aus einem FILE-Header liest ''std.rar'': Dateiflags, entpackte Größe, Attribute, optional Zeitstempel und CRC32, die Kompressionsinformation, das Wirtssystem und den Namen. Ein Eintrag wird nur übernommen, wenn **alle** vier Bedingungen zutreffen:
* es ist kein Verzeichnis (Flag-Bit 0 nicht gesetzt),
* die Kompressionsmethode ist ''0'' (//stored//; Bits 7–9 der Kompressionsinformation),
* die Namenslänge liegt zwischen 1 und 511 Byte,
* Datenbereich und Header liegen vollständig innerhalb der Datei.
> **Die Header-Prüfsumme wird gelesen, aber nicht geprüft.** Ein beschädigtes Archiv fällt deshalb nicht durch den CRC32-Vergleich auf, sondern erst, wenn Längenangaben aus der Datei laufen — dann bricht der Durchlauf ab und die bis dahin gefundenen Einträge bleiben stehen. ''RarCount'' kann also kleiner sein als der tatsächliche Archivinhalt, ohne dass ein Fehler gemeldet wird.
----
===== Fallstricke =====
* **Ein leeres Ergebnis heißt nicht „leeres Archiv".** ''RarCount'' = 0 bedeutet meistens: alle Einträge sind komprimiert. Vor der Fehlersuche mit ''7z l'' oder ''unrar l'' gegenprüfen.
* **Verzeichniseinträge fehlen** — sie werden nicht erfasst. Die Ordnerstruktur steckt nur in den Dateinamen (''daten/notiz.txt'').
* **Das Archiv liegt vollständig im Speicher.** ''RarOpen'' liest die ganze Datei; bei mehreren hundert MB entsprechend viel Hauptspeicher. Es gibt keinen streamenden Zugriff.
* **Namen sind interne Puffer**: ''RarName'' nie freigeben, und nach ''RarClose'' nicht mehr verwenden.
* **''RarRead'' terminiert nicht.** Der Rückgabewert ist die Zahl der kopierten Bytes; wer den Puffer als Text ausgeben will, setzt selbst ein Nullbyte dahinter (siehe Beispiel).
* **Mehrteilige Archive (''.part1.rar'') und verschlüsselte Archive** werden nicht unterstützt; verschlüsselte Blöcke erscheinen wie unbekannte Blocktypen und werden übersprungen.
* **RAR4 (''Rar!\x1A\x07\x00'') wird abgewiesen** — die Signaturprüfung verlangt RAR5.
----
===== Vergleich mit den anderen Archiv-Units =====
^ Unit ^ Lesen ^ Schreiben ^ Kompression ^
| [[lyx_-_programmiersprache:units:zip|std.zip]] | ja | ja | DEFLATE über ''std.zlib'' |
| [[lyx_-_programmiersprache:units:tar|std.tar]] | ja | ja | keine (mit ''std.gzip'' kombinierbar) |
| **std.rar** | **nur stored** | **nein** | keine |
| [[lyx_-_programmiersprache:units:iso|std.iso]] | ja | ja | keine |
----
**Weiterführend:** [[lyx_-_programmiersprache:units:archiv|Archiv — ZIP, TAR, RAR, ISO]] · [[lyx_-_programmiersprache:units:zip|std.zip]] · [[lyx_-_programmiersprache:units:gzip|std.gzip]]
**Quelle:** ''std/rar.lyx'' (311 Zeilen)
Letzte Aktualisierung: 2026-08-13 — Seite neu angelegt; sie fehlte bisher, obwohl die Archiv-Übersicht auf sie verlinkte. Inhalt gegen ''std/rar.lyx'' geschrieben und mit ''lyxc 1.0.21A'' gegen selbst erzeugte RAR5-Archive geprüft (eines nur mit //stored//, eines gemischt).
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).