Hallo Moritz,
Es ist normalerweise aus Performancegründen eine sehr
schlechte Idee, in einer Datei an beliebigen Stellen lesen zu
wollen.
Deshalb liest/bearbeitet man die Datei überlicherweise in
Blöcken, und lässt den Programmier auch spüren, dass er seine
Dateizugriffe auf den aktuellen Block beschränken soll.
ja, das ist klar. Genau deswegen möchte ich ja einen gepufferten
Zugriff, dass automatisch der Block in den Speicher geladen wird,
auf dem gerade gearbeitet wird. Aber ich möchte mich nicht mit
Arraygrenzen und Indexoffsets herumschlagen, wenn es sowas vielleicht
doch schon irgendwo fertig gibt.
Was willst du denn für eine Aufgabe erledigen, die random
access auf eine gesamte, große Datei erfordert? Vielleicht
gibt es ja eine bessere Lösung.
Na, ganz random access ist es nicht, sonst bräuchte ich ja gar
nicht zu puffern. Die Aufgabe ist folgende:
Ich hab unter OpenSuse den qemu laufen und emuliere mittlerweile
mein Win98 für die paar wenigen Anwendungen, die ich dann doch immer
wieder mal aus der Windows-Welt brauche. Dafür hab ich das File-System
in einem iso-image. Da aber der Emulator nicht gerade besonders schnell
ist, möchte ich mein Win möglichst schlank halten und alles, was das
System langsam macht draußen halten. Das erfordert viel probieren und
immer mal wieder ein altes image zurückspielen. Jetzt sind aber so 2GB
iso-Image recht unhandlich.
Also wollte ich mir ein binäres diff und patch-utility schreiben, das nur
jeweils die Differenz zu einem „Referenz-image“ speichert.
Ok, das ist jetzt weit ausgeholt. Aber für das diff muss ich über 2
files mit je 2GB laufen. Für das Patch muss ich das ganze wieder
rückwärts machen. Einfach wäre ein XOR bitweise und dann lauflängen-Codieren,
was mir ewig lange Ketten von Nullen rausschmeißt. Übrig bleiben im
Wesentlichen die Änderungen gegenüber dem Referenz-Image.
Was aber, wenn sich die Position von Dateien innerhalb des Images um ein Stück
verschiebt? dann muss ich ein Stück vor und zurück und vergleichen, ob die
passende Zeichenkette wo anders (aber immer noch etwa in der Nähe) in dem
Image vorkommt. I.d.R. wird sich das nicht weit verschieben, aber halt ein
Stückchen. Dafür brauche ich den Buffer, der dann für die eine und für die
andere Datei u.U. auch etwas versetzt läuft, eben je nach dem, wo der
Algorithmus die beste Übereinstimmung findet.
Beide Images komplett im Speicher zu haben ist ausgeschlossen.
Natürlich kann ich das blockweise Laden auch selbst machen. Ich dachte nur,
das ist doch eine Standard-Aufgabe, die bestimmt auch beim Brennen oder
Rippen von CDs/DVDs vorkommt und da müsste es doch wohl eine Library oder
etwas geben.
Such mal mit Google nach „Memory Mapped I/O“ oder „memory
mapped file“, vielleicht ist das ja was für dich (wobei ich
keine Ahnung habe, wie gut das mit großen Dateien
funktioniert).
Das nimmt einem das Laden und Speichern ab. Wenn die Datei aber nicht in den
RAM passt, dann muss man sich auch hier selbst mit der Unterteilung in Blöcke
auseinander setzen und die Array-Indizes entsprechend mit einem Offset in
Positionen im File umrechnen. Naja, aber wenn es das wohl doch nicht
fertig gibt, dann muss ich dafür eben doch eine eigene Klasse schreiben.
Grüße, Martin
PS: Ich hab auch schon nach binärem diff gesucht. Das gibt es, aber der
Haken ist bei den meisten Implementierungen gerade der Speicherbedarf.
Auch mit wine usw. hab ich schon rumprobiert. Da hätte man nicht das
Problem mit dem Image - man könnte einfach mit rsync und gzip usw. arbeiten -
nur zu dumm, dass eben nur die gängigsten Anwendungen von wine voll
unterstützt werden