Autor |
Beitrag |
drstar
Beiträge: 79
Erhaltene Danke: 2
Windows 8.1/x64
Delphi 10.1
|
Verfasst: Di 17.10.17 12:05
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:
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
Beiträge: 489
Erhaltene Danke: 14
Win 10, Win 8, Debian GNU/Linux
Delphi 10.1 Berlin, Java, C#
|
Verfasst: 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
Beiträge: 79
Erhaltene Danke: 2
Windows 8.1/x64
Delphi 10.1
|
Verfasst: 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
|
|
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Di 17.10.17 13:12
- Nachträglich durch die Entwickler-Ecke gelöscht -
|
|
drstar
Beiträge: 79
Erhaltene Danke: 2
Windows 8.1/x64
Delphi 10.1
|
Verfasst: 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
|
|
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Di 17.10.17 13:18
- Nachträglich durch die Entwickler-Ecke gelöscht -
|
|
haentschman
Beiträge: 285
Erhaltene Danke: 33
DX10 Berlin Professional
|
Verfasst: Di 17.10.17 14:31
Moin...
Eigentlich müßte sich eine moderne IDE bei:
K.isChanged = true
...sich weigern zu starten. (Scherz den du mal nachlesen solltest)
Für diesen Beitrag haben gedankt: baka0815
|
|
baka0815
Beiträge: 489
Erhaltene Danke: 14
Win 10, Win 8, Debian GNU/Linux
Delphi 10.1 Berlin, Java, C#
|
Verfasst: Mi 18.10.17 08:43
haentschman hat folgendes geschrieben : | Moin...
Eigentlich müßte sich eine moderne IDE bei:
K.isChanged = true
...sich weigern zu starten. (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
Beiträge: 79
Erhaltene Danke: 2
Windows 8.1/x64
Delphi 10.1
|
Verfasst: Mi 18.10.17 13:45
|
|
haentschman
Beiträge: 285
Erhaltene Danke: 33
DX10 Berlin Professional
|
Verfasst: Mi 18.10.17 14:22
Zitat: | und falsch ist es ja zum Glück nicht. |
..eben nicht.
Siehe: www.delphipraxis.net...ang-mit-boolean.html
Zitat: | Der Vergleich "BoolVar=True" kann sogar kräftig in die Hose gehen! |
|
|
drstar
Beiträge: 79
Erhaltene Danke: 2
Windows 8.1/x64
Delphi 10.1
|
Verfasst: 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
Beiträge: 285
Erhaltene Danke: 33
DX10 Berlin Professional
|
Verfasst: Do 19.10.17 08:01
Moin...
Zitat: | OK, das war mir neu, wieder was gelernt |
...das lob ich mir.
PS: Wenn du richtig programmieren willst, dann hört das nie auf.
|
|
baka0815
Beiträge: 489
Erhaltene Danke: 14
Win 10, Win 8, Debian GNU/Linux
Delphi 10.1 Berlin, Java, C#
|
Verfasst: 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.
|
|