Entwickler-Ecke
Dateizugriff - Lesen mit TFileStream liefert Müll
drstar - Di 17.10.17 12:05
Titel: Lesen mit TFileStream liefert Müll
So, neues Problem, nachdem ich die Datenbank-Problematik nun beseitigt habe.
Ich speichere die Inhalte der Objekte in eine Textdatei, das funktioniert auch, sind ohnehin nur Zahlen und Strings. Nur beim Einlesen kommt Müll raus - ich speichere 4 Strings hintereinander, jeweils vorgestellt mit Längenangabe. TFileStream liefert mir beim ersten String die ersten 3 Zeichen korrekt, die übrigen nimmt er von irgendwoher aus der Datei, als ob er mittendrin rumspringt.
Folgender Code:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28:
| type TFileStreamExt = class(TFileStream) procedure Delete(Pos, len: integer); procedure WriteString(aStr: string); function ReadString: string; end;
procedure TFileStreamExt.Delete(Pos: Integer; len: Integer); begin end;
function TFileStreamExt.ReadString: string; var aStrLen: Integer; begin Read(aStrLen, SizeOf(Integer)); SetLength(Result, aStrLen); Read(pointer(Result)^, aStrLen * SizeOf(AnsiChar)); end;
procedure TFileStreamExt.WriteString(aStr: string); var aStrLen: Integer; begin aStrLen := Length(aStr); Write(aStrLen, SizeOf(Integer)); Write(Pointer(aStr)^, aStrLen * SizeOf(Char)); end; |
Im Programm nutze ich TFileStreamExt wie folgt:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61:
| procedure ReadKlient(var K: TKlientExt); var i : integer; L: integer; begin if not assigned(K) then K.create; K.Position := Stream.Position -4; Stream.Read(K.Size, SizeOf(K.Size)); Stream.Read(K.Status, SizeOf(K.Status)); Stream.Read(K.Index, SizeOf(K.Index)); K.Vorname := Stream.ReadString; K.Nachname := Stream.ReadString; K.Strasse := Stream.ReadString; K.Ort := Stream.ReadString; K.isSaved := true; end;
procedure WriteKlient(K: TKlientExt); var L: Integer; OldPos, OldSize: integer; StartPos, EndPos : integer; const z : integer = 1; begin OldPos := K.Position; OldSize := K.Size; if (K.isSaved = false) or (K.isChanged = true) then begin StartPos := Stream.Position; Stream.Write(z, SizeOf(z)); Stream.Write(K.Size, SizeOf(K.Size)); Stream.Write(K.Status, SizeOf(K.Status)); Stream.Write(K.Index, SizeOf(K.Index)); Stream.WriteString(K.Vorname); Stream.WriteString(K.Nachname); Stream.WriteString(K.Strasse); Stream.WriteString(K.Ort); K.isSaved := true; EndPos := Stream.Position; K.Size := EndPos - StartPos; Stream.Position := StartPos +4; Stream.Write(K.Size, SizeOf(K.Size)); if K.isChanged = false then begin K.Position := StartPos; end; K.Size := EndPos - StartPos; Stream.Position := EndPos; end; if K.isChanged = true then begin Stream.Delete(OldPos, OldSize); DB_change(OldPos, OldSize); K.isSaved := true; K.isChanged := false; K.Position := StartPos; end; end; |
Wenn ich nun meinen Vornamen, Nachnamen, Strasse und Ort speichere, sieht alles korrekt aus - lese ich meinen Vornamen ein, stimmen die ersten 3 Zeichen, die übrigen 3 Zeichen gehören aber zu anderen Strings (ein Zeichen wohl zu meinem Nachnamen, und 2 zu meiner Strasse). Für mich wirkt es, als würde Filestream nicht hintereinander die Zeichen einlesen, was mache ich falsch? Die Länge der Strings ist korrekt gespeichert, das habe ich überprüft - bringt mir aber nichts, weil er nur die Länge des ersten Strings korrekt erfaßt, eben weil FileStream anschließend wild herumspringt und dann die Längenangabe des nächsten Strings nicht mehr trifft.
baka0815 - Di 17.10.17 13:06
Sieht nach einem Unicode-Problem aus.
ReadString() macht Read(pointer(Result)^, aStrLen * SizeOf(AnsiChar)); wohingegen du beim Schreiben Write(Pointer(aStr)^, aStrLen * SizeOf(Char)); verwendest.
Stell mal auch das Lesen um auf Read(pointer(Result)^, aStrLen * SizeOf(Char)); und gucke was passiert.
drstar - Di 17.10.17 13:11
waaaaaahhhh ich glaube es nicht.
Ich bin im Embarcadero-Hinweis um einen Absatz verrutscht - es lag tatsächlich am Unicode. Danke, ich hab schon hin- und herüberlegt, aber den Fehler habe ich nicht gesehen. Danke, es geht perfekt
Delete - Di 17.10.17 13:12
- Nachträglich durch die Entwickler-Ecke gelöscht -
drstar - Di 17.10.17 13:15
Frühlingsrolle hat folgendes geschrieben : |
Unicode, bei Delphi 6, ernsthaft? Char oder AnsiChar, wird auf AnsiChar hinauslaufen. |
Öhm ich aktualisiere mal meine Info... Delphi 10.1
Delete - Di 17.10.17 13:18
- Nachträglich durch die Entwickler-Ecke gelöscht -
haentschman - Di 17.10.17 14:31
Moin... :P
Eigentlich müßte sich eine moderne IDE bei:
K.isChanged = true
...sich weigern zu starten. :zwinker: (Scherz den du mal nachlesen solltest)
baka0815 - Mi 18.10.17 08:43
haentschman hat folgendes geschrieben : |
Moin... :P
Eigentlich müßte sich eine moderne IDE bei:
K.isChanged = true
...sich weigern zu starten. :zwinker: (Scherz den du mal nachlesen solltest) |
Guter Hinweis, du solltest tatsächlich nur
if K.isChanged statt mit
if K.isChanged = true abfragen.
Für den
False-Fall dann entsprechend mit
if not K.isSaved.
drstar - Mi 18.10.17 23:33
OK, das war mir neu, wieder was gelernt. Ich ging bislang immer davon aus, daß der Test auf true oder eben false korrekt ist; daß nur der Test auf false immer das richtige Ergebnis liefert, merke ich mir aber und werde meinen Programmcode mal entsprechend anpassen.
haentschman - Do 19.10.17 08:01
Moin... 8)
Zitat: |
OK, das war mir neu, wieder was gelernt |
...das lob ich mir. :zwinker:
PS: Wenn du richtig programmieren willst, dann hört das nie auf. :zwinker:
baka0815 - Do 19.10.17 12:29
Zum Tutorial: Die Zuweisung BoolVar := not (IntVar = 5); würde ich als BoolVar := (IntVar <> 5); schreiben, das ist deutlich klarer.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 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!