| Autor | Beitrag | 
| drstar 
          Beiträge: 79
 Erhaltene Danke: 2
 
 Windows 8.1/x64
 Delphi 10.1
 
 | 
Verfasst: Di 17.10.17 11: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 12: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 12: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 12: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 12: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 12:18 
 
- Nachträglich durch die Entwickler-Ecke gelöscht - | 
|  | 
| haentschman 
          Beiträge: 285
 Erhaltene Danke: 33
 
 
 DX10 Berlin Professional
 
 | 
Verfasst: Di 17.10.17 13: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 07: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 12:45 
 | 
|  | 
| haentschman 
          Beiträge: 285
 Erhaltene Danke: 33
 
 
 DX10 Berlin Professional
 
 | 
Verfasst: Mi 18.10.17 13: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 22: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 07: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 11:29 
 
Zum Tutorial: Die Zuweisung BoolVar := not (IntVar = 5); würde ich als BoolVar := (IntVar <> 5); schreiben, das ist deutlich klarer. | 
|  |