Autor |
Beitrag |
Einsamer Schütze
      
Beiträge: 37
XP Prof
Delphi 2007 professional
|
Verfasst: Di 18.11.08 20:54
Hallo Delphianer,
ich schon reichlich Zeit mit Suche in Foren verbracht.
Aber - mein Problem habe ich nicht lösen können und das sieht so aus:
Ich habe ein Record mit einem dyn. Array und einer Merkervariablen, in der ich einen Integerwert merken möchte.
Soweit scheint es auch gut zu tun.
Beim Auslesen bekomme ich mein Array wieder heraus - meinen Merker aber nicht. mE müsste er doch gespeichert sein - kann ich aber nicht überprüfen.
Das Auslesen des Merkers habe ich folgendermaßen versucht:
Delphi-Quelltext 1:
| myStream.Read(ErgRec.intAnzahl, sizeof(integer)); |
Dann das Array wie unten gelistet hinterher.
War leider nix.
Kann mir bitte jemand auf die Sprünge helfen.
Speichern:
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:
| try if fileexists('c:\temp\myRec.dat') then begin myStream := TFileStream.Create ('c:\temp\myRec.dat',fmOpenWrite); showmessage ('Datei gibt es.'); end else begin myStream := TFileStream.Create('c:\temp\myRec.dat', fmcreate); showmessage('Datei wurde neu angelegt'); end; if Length(ArrayRec.intArray) > 0 then begin ArrayRec.intAnzahl := Length(ArrayRec.intArray); myStream.Write(ArrayRec.intAnzahl, sizeof(integer));
for i := 0 to high(ArrayRec.intArray) do myStream.Write(ArrayRec.intArray[i],sizeof(ArrayRec.intArray)); end; finally myStream.free; |
Auslesen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| var myStream : TFileStream; i,len : integer; ErgRec : TArrayRec; strErg : string; begin
try myStream := TFileStream.Create ('c:\temp\myRec.dat', fmopenread);
if myStream.Size > 0 then begin
myStream.Read(len,sizeof(len)); setLength(ergRec.intArray, len); for i := 0 to (len - 1) do begin
myStream.Read(ErgRec.intArray[i], sizeof(len)); end; end; |
Vielen Dank,
ES
|
|
Xentar
      
Beiträge: 2077
Erhaltene Danke: 2
Win XP
Delphi 5 Ent., Delphi 2007 Prof
|
Verfasst: Di 18.11.08 22:03
Hast dir mal im Debugger die Variablen angeschaut?
Oder, die gespeicherte Datei mal mit einem Hex Editor geöffnet?
_________________ PROGRAMMER: A device for converting coffee into software.
|
|
Einsamer Schütze 
      
Beiträge: 37
XP Prof
Delphi 2007 professional
|
Verfasst: Mi 19.11.08 11:10
Ja, ich habe mittels Breakpoint im Debugger ermittelt, dass für den Fall mit Auslesen in die Merkervariable der erste Arraywert in die Merker-Variable reingeschrieben wird, das letze ArrayFeld dann aber irgend etwas enthält.
Bis zum Schreiben ist alles fein drin im Record.
Ich weiß nicht, was ich Hex-Editor erkennen könnte / sollte?
Danke,
ES
|
|
Gammatester
      
Beiträge: 328
Erhaltene Danke: 101
|
Verfasst: Mi 19.11.08 13:35
Wenn Du das Array lesen kannst, mußt Du doch vorher den Integer gelesen haben! In Deinem Lese-Code vermisse ich eine Anweisung der Art
Delphi-Quelltext
also etwa so
Delphi-Quelltext 1: 2: 3:
| myStream.Read(len,sizeof(len)); ergRec.intAnzahl := len; setLength(ergRec.intArray, len); |
Gammatester
|
|
baka0815
      
Beiträge: 489
Erhaltene Danke: 14
Win 10, Win 8, Debian GNU/Linux
Delphi 10.1 Berlin, Java, C#
|
Verfasst: Mi 19.11.08 16:09
|
|
Einsamer Schütze 
      
Beiträge: 37
XP Prof
Delphi 2007 professional
|
Verfasst: Mi 19.11.08 22:34
@ Gammatester
len ist ein Integer - er liest hier definitiv den ersten Wert des Arrays aus.
da liegt der fehler nicht, zumindest nicht allein.
ich bin ja auch der meinung, dass mein integer vor dem array liegen müsste - im stream. aber wer weiß das schon so genau.
@ baka
habe ich getestet, ist ja letztlich ein integer da drin. sowohl sizeof (ganzesArray) als auch sizeof(integer) kommen zum gleichen ergebnis - es scheint keinen unterschied zu machen - frag mich bitte nicht, warum, oder sag's mir.
ALSO, nach meiner interpretation müsste doch
Delphi-Quelltext 1:
| myStream.Read(len,sizeof(len)); |
die anzahl der menge an integers im stream ermitteln - es sind ja nur integers drin. aber mein merker kommt nicht vor.
MUSS ich das record packed setzen - ich habe da mal etwas gelesen?
Danke trotzdem erstmal.
ES
|
|
Xentar
      
Beiträge: 2077
Erhaltene Danke: 2
Win XP
Delphi 5 Ent., Delphi 2007 Prof
|
Verfasst: Mi 19.11.08 22:58
Welchen Merker meinst du eigentlich..?!
Du schreibst rein:
- Einen Integer (Die Anzahl der Array-Elemente)
- Die einzelnen Werte des Arrays.
Du liest aus:
- Einen Integer
- Mehrere Integers, abhängig vom zuvor gelesen Wert.
Also passt das doch? Welchen Merker meinst du denn, der angeblich vermisst wird?
_________________ PROGRAMMER: A device for converting coffee into software.
|
|
Einsamer Schütze 
      
Beiträge: 37
XP Prof
Delphi 2007 professional
|
Verfasst: Mi 19.11.08 23:15
xentar, der merker soll der mitgelieferte arraycount sein, genau der fehlt aber. es sind nur die daten aus dem array da. den count merker bekomme ich nicht.
bsp: ich gebe ein
122, 133, 144
counter ist 3.
das schreibe ich weg (oder bemühe mich darum).
ich lese aus:
ergRec.intArray ->(122, 133, 144)
ergRec.intArray.intAnzahl -> irgendwas
versuche ich zuerst in die intAnzahl zu ermitteln, steht da die erste array zahl drin (122), dafür hat die letzte array-variable dann den wert irgendwas.
danke allemal,
ES
|
|
Xentar
      
Beiträge: 2077
Erhaltene Danke: 2
Win XP
Delphi 5 Ent., Delphi 2007 Prof
|
Verfasst: Do 20.11.08 00:19
Also.. ich hab mir nun mal die Mühe gemacht, und dein Problem nachgebaut:
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: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure Button2Click(Sender: TObject); private FTestArray: array of integer; public end;
var Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject); var MyStream: TFileStream; i, len: integer; begin try if fileexists('c:\temp\myRec.dat') then begin myStream := TFileStream.Create ('c:\temp\myRec.dat',fmOpenWrite); showmessage ('Datei gibt es.'); end else begin myStream := TFileStream.Create('c:\temp\myRec.dat', fmcreate); showmessage('Datei wurde neu angelegt'); end;
if Length(FTestArray) > 0 then begin len := length(FTestArray); myStream.Write(len, sizeof(integer));
for i := 0 to high(FTestArray) do myStream.Write(FTestArray[i],sizeof(FTestArray)); end; finally myStream.free; end;
end;
procedure TForm1.Button2Click(Sender: TObject); var MyStream: TFileStream; i, len: integer; begin try myStream := TFileStream.Create ('c:\temp\myRec.dat', fmopenread);
if myStream.Size > 0 then begin
myStream.Read(len,sizeof(len)); setLength(FTestArray, len);
for i := 0 to (len - 1) do begin myStream.Read(FTestArray[i], sizeof(len)); end; end; finally freeandnil(mystream); end;
ShowMessage(IntToStr(ftestarray[0])); end;
procedure TForm1.FormCreate(Sender: TObject); begin SetLength(FTestArray, 3); FTestArray[0] := 111; FTestArray[1] := 222; FTestArray[2] := 333; end;
end. |
Hab deinen Source größtenteils kopier, daher die grausige Formatierung
Vorgehensweise:
- Starten -> Button 1 zum Speichern anklicken -> Datei wird erfolgreich angelegt, sieht auch im Hex Editor gut aus.
- Den Teil im OnCreate auskommentieren -> Starten -> Button 2 anklicken. Richtiges Ergebnis 111 wird angezeigt.
Also irgendwie hast du ein anders Problem...
Edit: Deswegen sag ich ja, schau dir die Datei in nem Hex Editor an, und guck, ob die ersten Bytes stimmen.. Dann weißt du schonmal, ob das Problem beim Speichern, oder beim Laden ist.
_________________ PROGRAMMER: A device for converting coffee into software.
|
|
Einsamer Schütze 
      
Beiträge: 37
XP Prof
Delphi 2007 professional
|
Verfasst: Do 20.11.08 17:38
Also ich gebe mal jetzt den kompletten Code hier ein, sonst verstehe ich vielleicht nicht richtig, was Ihr meint, oder auch umgkehrt.
Vielleicht kann das ja einer mal kopieren und nachbauen, und mir helfen. Sowas darf doch eigentlich nicht so schwer sein, dachte ich...
Danke schon mal.
ES
@ Xentar --> das mit dem Code-Format war gemein, das hat mich drei Therapiestunden gekosten...
-----------------------------------------------------------------
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: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131:
| unit UArray_mit_Streams3;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TfrmStreams = class(TForm) btnSchreibe: TButton; btnLies: TButton; Edit1: TEdit; btnHinzu: TButton; ListBox1: TListBox;
procedure btnSchreibeClick(Sender: TObject); procedure btnLiesClick(Sender: TObject); procedure btnHinzuClick(Sender: TObject); procedure FormCreate(Sender: TObject); private public end;
type TArrayRec = Record intArray : array of integer; intAnzahl : integer; End;
var frmStreams: TfrmStreams; intWerte : array of integer; ArrayRec : TArrayRec;
implementation
{$R *.dfm}
procedure TfrmStreams.btnSchreibeClick(Sender: TObject); var myStream: TFileStream; i,mb : integer; begin
try if fileexists('c:\temp\myRec.dat') then begin myStream := TFileStream.Create('c:\temp\myRec.dat', fmOpenWrite); showmessage ('Datei gibt es'); end else begin myStream := TFileStream.Create('c:\temp\myRec.dat', fmcreate); showmessage('Datei wurde neu angelegt'); end; if Length(ArrayRec.intArray) > 0 then begin ArrayRec.intAnzahl := Length(ArrayRec.intArray); myStream.Write(ArrayRec.intAnzahl, sizeof(integer));
for i := 0 to high(ArrayRec.intArray) do myStream.Write(ArrayRec.intArray[i], sizeof(integer)); end; finally myStream.free; end;
end;
procedure TfrmStreams.FormCreate(Sender: TObject); begin
arrayrec.intanzahl := 0; end; procedure TfrmStreams.btnHinzuClick(Sender: TObject); var intLaenge : integer; begin
inc(ArrayRec.intAnzahl); setlength(ArrayRec.intArray, ArrayRec.intAnzahl);
ArrayRec.intArray[ArrayRec.intAnzahl -1] := strtoint(Edit1.Text); end; procedure TfrmStreams.btnLiesClick(Sender: TObject); var myStream : TFileStream; i,len : integer; ErgRec : TArrayRec; strErg : string; begin
try myStream := TFileStream.Create('c:\temp\myRec.dat', fmopenread);
if myStream.Size > 0 then begin
myStream.Read(len,sizeof(len)); setLength(ergRec.intArray, len);
for i := 0 to (len - 1) do begin
myStream.Read(ErgRec.intArray[i], sizeof(len)); end; end; for i := 0 to (len - 1) do ListBox1.AddItem (inttostr(ErgRec.intArray[i]),Listbox1);
finally myStream.Free; end;
end; end. |
|
|
Einsamer Schütze 
      
Beiträge: 37
XP Prof
Delphi 2007 professional
|
Verfasst: So 23.11.08 21:29
Hallo Delphianer, ich habe jetzt mal mit einem Hex-Editor die Datei aufgemacht.
Für die Zahlen 0-9 im Array findet sich folgendes Gehexe:
0A00000000000000 0100000002000000
0300000004000000 0500000006000000
0700000008000000 09000000
Für 10-15
060000000A000000 0B0000000C000000 0D0000000E000000 0F000000
Passt also alles, der erste Wert ist mein Merker.
Es liegt definitiv an meiner Lese-Routine.
Wenn ich meinen Code so ändere
Delphi-Quelltext 1: 2: 3: 4: 5:
| myStream.Read(ergRec.intAnzahl,sizeof(ergRec.intAnzahl));
myStream.Read(len,sizeof(len));
setLength(ergRec.intArray, len); |
Dann bekomme ich meinen Integer-Wert, aber nichts Sinnvolles im Array.
Es ist alles im LeseStream, nur irgend etwas fehlt, um die Sache koordiniert rauszuholen.
Ich könnte ja den Stream dann zumachen und das Ganze nochmal auslesen, aber das wäre ja doch etwas sehr wüst. Ich möchte ja die Technik verstehen.
LG
ES
|
|
Xentar
      
Beiträge: 2077
Erhaltene Danke: 2
Win XP
Delphi 5 Ent., Delphi 2007 Prof
|
Verfasst: So 23.11.08 22:16
Hm.. setz doch bitte, bevor du den ersten Wert ausliest, ein MyStream.Position := 0;
Normalerweise sollte das schon sein, nachdem man den Stram öffnet.. aber eine andere Idee hab ich grad nicht.
_________________ PROGRAMMER: A device for converting coffee into software.
|
|
Einsamer Schütze 
      
Beiträge: 37
XP Prof
Delphi 2007 professional
|
Verfasst: So 23.11.08 23:28
Danke Xentar, habe ich getan.
Ich habe Deine Zeile an verschiedenen Stellen - vor dem ersten Auslesen und vor der Array-Schleife - getestet.
Dann wird der letzte Array-Wert an die erste Stelle geschrieben (5,1,2,3,4), der Merker kommt nicht raus.
Tja, mal sehen, was man noch so veranstalten kann.
Für heute erst mal Schluss.
LG
ES
|
|
baka0815
      
Beiträge: 489
Erhaltene Danke: 14
Win 10, Win 8, Debian GNU/Linux
Delphi 10.1 Berlin, Java, C#
|
Verfasst: Mo 24.11.08 12:58
Einsamer Schütze hat folgendes geschrieben : |
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:
| procedure TfrmStreams.btnLiesClick(Sender: TObject); var myStream : TFileStream; i,len : integer; ErgRec : TArrayRec; strErg : string; begin
try myStream := TFileStream.Create('c:\temp\myRec.dat', fmopenread);
if myStream.Size > 0 then begin
myStream.Read(len,sizeof(len)); setLength(ergRec.intArray, len);
for i := 0 to (len - 1) do begin
myStream.Read(ErgRec.intArray[i], sizeof(len)); end; end; for i := 0 to (len - 1) do ListBox1.AddItem (inttostr(ErgRec.intArray[i]),Listbox1);
finally myStream.Free; end;
end; | |
Du liest die Anzahl der Einträge in len ein, weißt diesen Wert jedoch nie intAnzahl zu.
|
|
Gammatester
      
Beiträge: 328
Erhaltene Danke: 101
|
Verfasst: Mo 24.11.08 16:35
baka0815 hat folgendes geschrieben : | Du liest die Anzahl der Einträge in len ein, weißt diesen Wert jedoch nie intAnzahl zu. |
Das hatte ich schon im 4. Beitrag geschrieben, aber angeblich soll das nichts bringen. Ich weiß zwar nicht, weshalb das nichts bringt oder ob es überhaupt getestet wurde; aber man muß sich halt auf die Antworten verlassen können.
Gammatester
|
|
Einsamer Schütze 
      
Beiträge: 37
XP Prof
Delphi 2007 professional
|
Verfasst: Mo 24.11.08 17:33
Gammatester,
Du hast Recht und ich entschuldige mich dafür, dass ich das nicht getestet habe, wie Du es schriebst. -->> Ich hatte lediglich einen Breakpoint reingesetzt und mir dann angeschaut, was in dem Record drinsteht.<<-- Weil er ja in das ergRecord gültige Werte reinschreibt, aber eben mit den obigen Resultaten.
myStream.Read(len,sizeof(integer));
ergRec.intAnzahl := len;
tut, wie Du sagst.
Da muss ich wohl in mein Kämmerlein gehen und penibler werden;
sei mir nicht sauer.
ES
@Xentar, Danke.
|
|
Gammatester
      
Beiträge: 328
Erhaltene Danke: 101
|
Verfasst: Mo 24.11.08 17:55
Kein Problem, Hauptsache es funktioniert jetzt.
Gammatester
|
|
|