Autor Beitrag
Rekursion
Hält's aus hier
Beiträge: 8



BeitragVerfasst: So 10.10.10 16:27 
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:
www.schule.de/schule...n/pascal_dateien.htm
Welches Konzept würdet ihr verwenden?
Gerd Kayser
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: So 10.10.10 16:50 
user profile iconRekursion hat folgendes geschrieben Zum zitierten Posting springen:
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.
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: 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 Threadstarter
Hält's aus hier
Beiträge: 8



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: So 10.10.10 17:23 
user profile iconRekursion hat folgendes geschrieben Zum zitierten Posting springen:
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: www.delphi-treff.de/...als/datenspeicherung
Weitere Quellen findest Du leicht über Google, wenn Du "tfilestream tutorial" als Suchbegriff verwendest.
Rekursion Threadstarter
Hält's aus hier
Beiträge: 8



BeitragVerfasst: Mo 11.10.10 16:44 
Wenn ich jetzt zB. so was mache:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var
Stream1 : TStream;

begin
Stream1 := TFileStream.Create('irgendeine Datei', fmCreate);

//Hier kommts:
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 user profile iconNarses: Code- durch Delphi-Tags ersetzt
bummi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1248
Erhaltene Danke: 187

XP - Server 2008R2
D2 - Delphi XE
BeitragVerfasst: Mo 11.10.10 17:51 
Ansistrings verwenden
oder in Deinem beispiel

Stream1.Write(AnsiString('HalloWelt!'), 10);


Oder die Länge "richtig übergeben"
ausblenden 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 Threadstarter
Hält's aus hier
Beiträge: 8



BeitragVerfasst: Mo 11.10.10 18:50 
OK, wenn ich das so schreibe:
ausblenden 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ß.

ausblenden 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 user profile iconNarses: Code- durch Delphi-Tags ersetzt
Flamefire
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 31

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: 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 Threadstarter
Hält's aus hier
Beiträge: 8



BeitragVerfasst: Di 12.10.10 14:43 
Ich weiß nicht, ob du das so meinst:

ausblenden 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 user profile iconNarses: Code- durch Delphi-Tags ersetzt
Flamefire
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 31

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: 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));

Für diesen Beitrag haben gedankt: Rekursion
Rekursion Threadstarter
Hält's aus hier
Beiträge: 8



BeitragVerfasst: Di 12.10.10 15:03 
Ah, cool, jetzt funktioniert es.