Entwickler-Ecke
Dateizugriff - Lesen und schreiben von Chunkdateien (Chunk-Gliederung)
Rekursion - So 10.10.10 16:27
Titel: Lesen und schreiben von Chunkdateien (Chunk-Gliederung)
Hallo, ich muss für die Schule ein Teil eines Projekts in Delphi machen, obwohl ich mich gar nicht so gut in Delphi auskenne, besser gesagt bin ich in Delphi völlig nop. Was ich in anderen Programmiersprechen schon 100mal gemacht habe, bekomme ich hier einfach nicht hin.
Mein Problem:
Ich musste ein Dateiformat entwerfen, in das Projekt Daten speichern kann (was genau ist ja hier unwichtig). Ich habe mich für ein Chunkgegliedertes Dateiformat entschieden, da das von modernen Anwendungen eben so gemacht wird. Ich will
also mehrere Informationsbrocken, die in beliebiger Reihenfolge stehen können und aus folgendem bestehen:
-4 Byte Bezeichner für den Chunk-Typ
-4 Byte Größe des Folgenden Chunkinhalts
-Inhalt des Chunks, ohne spezielle Kodierung, hier stehen also irgendwelche Bytes
Das ganze hört sich ganz toll an, nur mein Problem: Das muss ich jetzt alles Implementieren, ich muss also für folgende Aufgaben Funktionen implementieren:
-Alle Chunks auflisten
-Den Inhalt bestimmter Chunks auslesen
-Den Inhalt bestimmter Chunks verändern
Die Funktionen sollen unbekannte Chunks einfach überspringen. Ausserdem ist die Reihenfolge der Chunks nicht festgesetzt.
Da ich mich mit Dateizugriff in Delphi nicht auskenne, konnte ich selbst noch nicht viel ansetzen. Ich bin bei Google auf das hier gestoßen:
http://www.schule.de/schulen/oszhdl/gymnasium/faecher/informatik/rechnerarchitektur/dateien/pascal_dateien.htm
Welches Konzept würdet ihr verwenden?
Gerd Kayser - So 10.10.10 16:50
Rekursion hat folgendes geschrieben : |
Welches Konzept würdet ihr verwenden? |
1. TextFile ist ungeeignet, weil Du ja beliebige binäre Daten schreiben willst.
2. File Of Records ist ungeeignet, weil Deine Chunks unterschiedlich groß sind.
3. Untypisierte Dateien wären geeignet, allerdings geht beim Schreiben größerer Dateien die Performance massiv in die Knie.
Bleibt also nur noch
4. FileStream. Wenn Du zum Lesen / Schreiben geeignete Größen für den Buffer wählst, ist das von der Performance her absolute Spitze.
Delete - So 10.10.10 17:07
Records gehen schon. Man sollte nur die Länge des Chunks mit Abspeichern. Oder alternativ XML, da kann man auch binäre Daten speichern. Eventuell vorher codieren.
Rekursion - So 10.10.10 17:08
Ja, an 3 oder 4 Dachte ich auch. Die Dateien sind eigentlich nicht so groß, so bis zu 20 KB max!
Kennt jemand ein Tutorial, bei dam das mit den FileStreams für Delphi-nops erklärt wird?
Aus anderen Programmiersprechen weiß ich, wie das mit FileStreams geht, ich kenne nur die Implementierung nicht.
Gerd Kayser - So 10.10.10 17:23
Rekursion hat folgendes geschrieben : |
Ja, an 3 oder 4 Dachte ich auch. Die Dateien sind eigentlich nicht so groß, so bis zu 20 KB max! |
Dann kannst Du 3 und 4 verwenden. Mit größeren Dateien hatte ich so Größenordnungen von einigen zig MB aufwärts im Sinn.
Zitat: |
Kennt jemand ein Tutorial, bei dam das mit den FileStreams für Delphi-nops erklärt wird? |
z. B. hier:
http://www.delphi-treff.de/tutorials/datenspeicherung
Weitere Quellen findest Du leicht über Google, wenn Du "tfilestream tutorial" als Suchbegriff verwendest.
Rekursion - Mo 11.10.10 16:44
Wenn ich jetzt zB. so was mache:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| var Stream1 : TStream;
begin Stream1 := TFileStream.Create('irgendeine Datei', fmCreate);
Stream1.Write('HalloWelt!', 10); |
Dann schreibt Delphi so was: H.a.l.l.o.
Das sind zwar auch 10 Bytes, von meinem String wurden aber nur die ersten 5 Bytes übernommen und dafür jedes zweite Byte nicht gesetzt (0).
Ich vermute, dass das an der Kodierung liegt: Delphi nimmt meinen String vielleicht als Unicode auf, der dann eigentlich 20 Bytes hätte.
Wie kann ich den String zum 8-Bit-ASCI zwingen, also umwandeln?
Moderiert von
Narses: Code- durch Delphi-Tags ersetzt
bummi - Mo 11.10.10 17:51
Ansistrings verwenden
oder in Deinem beispiel
Stream1.Write(AnsiString('HalloWelt!'), 10);
Oder die Länge "richtig übergeben"
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| Function GetLength(const s:AnsiString):Integer;overload; begin Result := Length(s); end;
Function GetLength(const s:WideString):Integer;overload; begin Result := Length(s)*2; end;
Function GetLength(const s:String):Integer;overload; begin Result := Length(s) * SizeOf(Char); end; |
Rekursion - Mo 11.10.10 18:50
OK, wenn ich das so schreibe:
Delphi-Quelltext
1:
| Stream1.Write(AnsiString('HALLO'), 5); |
funktioniert das ganz gut.
Doch irgendwie komme ich mit dem Auslesen der Länge nicht klar, also zB. wenn ich einen String habe,
dessen Länge ich nicht weiß.
Delphi-Quelltext
1: 2: 3: 4:
| var string1:string; begin string1 := 'irgendwas mit unbekannter laenge'; Stream1.Write(AnsiString(string1), SizeOf(AnsiString(string1))); |
Wieso funktioniert das nicht? Ich hab doch einen AnsiString, den will ich schreiben, und ich hab die Größe in Bytes von diesem AnsiString.
Moderiert von
Narses: Code- durch Delphi-Tags ersetzt
Flamefire - Mo 11.10.10 19:15
AnsiString ist kein Makro sondern eine Funktion, die den String tatsächlich umwandelt. Definiere string1 lieber gleich als Ansistring.
Dann Abfrage per Length()
SizeOf gibt die Größe eines DatenTYPs zurück. Funktioniert also nicht mit was variablen wie dynamische Arrays und Strings.
PS: Zwecks Performance kannst du am Ende auch auf meine TFastFileStream Klasse setzen. Wenn du korrekt programmierst (Also "Stream1:TStream" geschrieben hast) musst du am Ende nur den Konstruktoraufruf ändern und hast TFileStream gegen TFastFileStream getauscht.
Rekursion - Di 12.10.10 14:43
Ich weiß nicht, ob du das so meinst:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| procedure TForm1.Button1Click(Sender: TObject); var Stream : TStream; var inhalt : AnsiString; begin Stream := TFileStream.Create('c:\testfile.txt', fmCreate); inhalt := 'Hallo Welt, das ist ein Text unbekannter Laenge, da die Zeichen' + 'nur von Delphi je gezaehlt werden,' + 'blabla, i love Delphi, etc...'; Stream.Write(inhalt, Length(inhalt)); Stream.Free; end; |
Jetzt steht irgendwas in der Datei, irgendwelchen Kryptozeichen eben, aber von dem Text kann ich nichts sehen.
Moderiert von
Narses: Code- durch Delphi-Tags ersetzt
Flamefire - Di 12.10.10 14:49
Ist erst mal richtig.
Versuch mal bei Arrays und Strings den Index mit anzugeben. Bei Arrays (meist) 0 und bei Strings 1
Also: Stream.Write(inhalt[1], Length(inhalt));
Rekursion - Di 12.10.10 15:03
Ah, cool, jetzt funktioniert es.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!