Autor Beitrag
drstar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 79
Erhaltene Danke: 2

Windows 8.1/x64
Delphi 10.1
BeitragVerfasst: 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:

ausblenden 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
  //spielt hier keine Rolle, nur der Vollständigkeit halber aufgeführt
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:

ausblenden volle Höhe 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;   // soll so sein, weil der Aufruf dieser Methode aufgrund eines Integers erfolgt, der vorher eingelesen wurde, beim Schreiben aber dem Objekt zugeschrieben wird
    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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 489
Erhaltene Danke: 14

Win 10, Win 8, Debian GNU/Linux
Delphi 10.1 Berlin, Java, C#
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 79
Erhaltene Danke: 2

Windows 8.1/x64
Delphi 10.1
BeitragVerfasst: 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



BeitragVerfasst: Di 17.10.17 13:12 
- Nachträglich durch die Entwickler-Ecke gelöscht -
drstar Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 79
Erhaltene Danke: 2

Windows 8.1/x64
Delphi 10.1
BeitragVerfasst: Di 17.10.17 13:15 
user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
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



BeitragVerfasst: Di 17.10.17 13:18 
- Nachträglich durch die Entwickler-Ecke gelöscht -
haentschman
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 285
Erhaltene Danke: 33


DX10 Berlin Professional
BeitragVerfasst: 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)

Für diesen Beitrag haben gedankt: baka0815
baka0815
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 489
Erhaltene Danke: 14

Win 10, Win 8, Debian GNU/Linux
Delphi 10.1 Berlin, Java, C#
BeitragVerfasst: Mi 18.10.17 08:43 
user profile iconhaentschman hat folgendes geschrieben Zum zitierten Posting springen:
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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 79
Erhaltene Danke: 2

Windows 8.1/x64
Delphi 10.1
BeitragVerfasst: Mi 18.10.17 13:45 
user profile iconbaka0815 hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconhaentschman hat folgendes geschrieben Zum zitierten Posting springen:
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.


Alte Angewohnheit von mir, und falsch ist es ja zum Glück nicht.
haentschman
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 285
Erhaltene Danke: 33


DX10 Berlin Professional
BeitragVerfasst: Mi 18.10.17 14:22 
Zitat:
und falsch ist es ja zum Glück nicht.

:mahn: ..eben nicht.
Siehe: www.delphipraxis.net...ang-mit-boolean.html
Zitat:
Der Vergleich "BoolVar=True" kann sogar kräftig in die Hose gehen!
drstar Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 79
Erhaltene Danke: 2

Windows 8.1/x64
Delphi 10.1
BeitragVerfasst: Mi 18.10.17 23:33 
user profile iconhaentschman hat folgendes geschrieben Zum zitierten Posting springen:
Zitat:
und falsch ist es ja zum Glück nicht.

:mahn: ..eben nicht.
Siehe: www.delphipraxis.net...ang-mit-boolean.html
Zitat:
Der Vergleich "BoolVar=True" kann sogar kräftig in die Hose gehen!


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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 285
Erhaltene Danke: 33


DX10 Berlin Professional
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 489
Erhaltene Danke: 14

Win 10, Win 8, Debian GNU/Linux
Delphi 10.1 Berlin, Java, C#
BeitragVerfasst: 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.