Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Record Array speichern und lesen...Error (https://www.delphipraxis.net/154457-record-array-speichern-und-lesen-error.html)

Codix32 11. Sep 2010 13:03

Delphi-Version: 2005

Record Array speichern und lesen...Error
 
Hallöchen

ich kriegs nicht hin. Möchte ein dynamisches Record Array, das in eine Datei gespeichert ist auslesen und kriege ständig Fehlermeldungen.

Habe die Leseroutine im Internet gefunden und komme insbesonders mit der 'Blockread Procedur' nicht klar.

Die gefundene Routine weißt wohl schon einen Fehler auf, nämlich hier:
Delphi-Quellcode:
procedure ReadFile(filename:string);
var   fil:   file;
        i:     integer;
        num:   word;    {allows up to 65535 records}
ver:   byte;
 
   function ReadString:ShortString;
   begin  {ReadString}
     BlockRead(fil,result,1);              {Read the length of the string}
     BlockRead(fil,s[1],length(s)); //<- s ist nirgends declariert
   end;  {ReadString}

begin  {ReadFile}
...
...
Ich habe versucht , einfach in der Funktion eine Variable vom Typ Shortstring zu erstellen:
Delphi-Quellcode:
  function ReadString:ShortString;
   var
   s:string;
   begin  {ReadString}
     BlockRead(fil,result,1);              {Read the length of the string}
     BlockRead(fil,s[1],length(s));        {Read the string itself}
   end;  {ReadString}
Funzt nicht. Was passiert hier eigentlich? Die Blockread Procedure bekommt in der Funktion das Resultat der Funktion übergeben, mein Verstand reicht da nicht mehr hin.

Hier nochmal die ganze Leseroutine:
Delphi-Quellcode:
procedure TForm1.ReadFile(filename:string);
var   fil:   file;
        i:     integer;
        num:   byte;    {allows up to 65535 records}
ver:   byte;

   function ReadString:ShortString;
   var
   s:string;
   begin  {ReadString}
     BlockRead(fil,result,1);              {Read the length of the string}
     BlockRead(fil,s[1],length(s));        {Read the string itself}
   end;  {ReadString}

begin  {ReadFile}
   assignFile(fil,filename); reset(fil,1); {Open the file}
   BlockRead(fil,ver,sizeof(ver));     {Read the file version}
   BlockRead(fil,num,sizeof(num));     {Read the number of records}
   SetLength(VBilArray,num);
   for i:=0 to high(VBilArray) do
       with VBilArray[i] do begin     {Read the data}
         Schuldsum:=ReadString;
         Rate:=ReadString;
         RFaellig:=strtoint(ReadString);
         Abbuchungstag:=ReadString;
       end;  {with}
   CloseFile(fil);
end;  {ReadFile}
Kann mir jemand helfen?

mkinzler 11. Sep 2010 13:07

AW: Record Array speichern und lesen...Error
 
Wenn der Record keine dynmsichen Felder besitzt, würde sich eine typisierte Datei anbieten

[Edit: Array durch Record ersetzt]

himitsu 11. Sep 2010 13:08

AW: Record Array speichern und lesen...Error
 
Zitat:

Delphi-Quellcode:
//<- s ist nirgends declariert

Ich würde stattdessen mal Result verwenden ... dort soll der Text doch wohl auch rein.

Zitat:

Delphi-Quellcode:
BlockRead(fil,result,1);

Auch wenn das so funktioniert, wäre hier
Delphi-Quellcode:
Result[0]
besser/verständlicher, als nur das
Delphi-Quellcode:
Result
,
da an dieser Stelle auch nur dieses Feld eingelesen wird.

Codix32 11. Sep 2010 13:29

AW: Record Array speichern und lesen...Error
 
Zitat:

Zitat von mkinzler (Beitrag 1048883)
Wenn der Record keine dynmsichen Felder besitzt, würde sich eine typisierte Datei anbieten

[Edit: Array durch Record ersetzt]

Hat er wohl nicht:
Delphi-Quellcode:
type
TBilanz = packed record
 Schuldsum   :string[10];           //<-gesamte Schuldsumme
 Rate        :string[8];            //<-Rate
 RFaellig    :byte;                 //<-monatlich oder vierteljährlich
 Abbuchungstag:string[2];            //<-Abbuchungstag
end;

type
TBilArray = array of TBilanz;

mkinzler 11. Sep 2010 13:32

AW: Record Array speichern und lesen...Error
 
Dann wäre das ja eine Option

Codix32 11. Sep 2010 13:47

AW: Record Array speichern und lesen...Error
 
Zitat:

Zitat von mkinzler (Beitrag 1048890)
Dann wäre das ja eine Option

mKinzler, ich habe hier eine Routine mit 'Writeln und Readln', die auch funktioniert. Aber es läßt mir keine Ruhe, wenn ich eine Routine finde, ausprobiere, Fehler erhalte und ich das Dingens nicht verstanden habe. Ich habe erst Ruhe, wenn die Routine ihren Zweck erfüllt.

Außerdem ist die Datei viel schlanker als wenn ich die Daten in eine 'TextFile' mit writeln schreibe.
Die Routinen sind alle hier zu finden:
http://www.delphicorner.f9.co.uk/articles/misc15.htm

Codix32 11. Sep 2010 14:04

AW: Record Array speichern und lesen...Error
 
Ups, was sehen meine Äugelein?

Der Fehler ist schon in der Write Routine. Da werden die Nummer der Datei (latestFileVersion) und die Recordnummern(Number of Records->num) nicht gespeichert oder gleich mit dem Array Inhalt überschrieben. Jedenfalls felhen in der Datei die beiden Zahlen 3 für Version und 3 bzw. 2 für die Indexe:
Delphi-Quellcode:
Const
   LatestFileVersion = 3;
//......
.......
procedure TForm1.WriteFile(filename:string);
var
  fil: file;
  i: integer;
  num: byte;
const ver:   byte = LatestFileVersion; //<- Const LatestFileVersion = 3; steht nicht in der Datei

    procedure WriteString(s:ShortString);
    begin
     BlockWrite(fil,s,succ(length(s)));
    end;

begin
   assignFile(fil,filename); rewrite(fil,1);
   BlockWrite(fil,ver,sizeof(ver));
   num:=length(VBilArray);
   Label8.Caption:=inttostr(num)+'   '+inttostr(ver);
   BlockWrite(fil,num,sizeof(num));  //<- steht auch nicht in der MArray.txt
      for i:=0 to high(VBilArray) do
        with VBilArray[i] do begin
        WriteString(Schuldsum);
        WriteString(Rate);
        WriteString(inttostr(RFaellig));
        WriteString(Abbuchungstag);
        end;
   CloseFile(fil);
end;
//---------------------------------------------------------
procedure TForm1.Button6Click(Sender: TObject);
begin
WriteFile('MArray.txt');
end;

Codix32 12. Sep 2010 13:06

AW: Record Array speichern und lesen...Error
 
Vielen Dank mKinzler und himitsu

das Problem hat sich gelöst.

Erstens wird die Version und der Highindex in der Datei sehr wohl gespeichert, aber als hex 03 und hex 05. Mein Hexeditor hats mir verraten.

Zweitens, die in der WriteFile für den Array index stehende Variable 'num' wird in der For Schleife als High Index benutzt.
Die Funktion 'length' gibt 3 Indexe aus. Da aber das Array bei Index 0 beginnt, darf die Schleife nur von 0 bis einschlieslich 2 gehen.
Das war wohl Fehlermeldung: "EInOuterror: Versuch über das Dateiende hinauszulesen". Oder auch der EConvertError mit irgendwelchen kryptischen Zeichen ist weg.
Delphi-Quellcode:
procedure TForm1.WriteFile(filename:string);
....
...
begin  {WriteFile}
   assignFile(fil,filename); rewrite(fil,1); {Create the file}
   BlockWrite(fil,ver,sizeof(ver));                  
   num:=length(VBilArray)-1;           //<- -1 sonst ist 'num' um 1 zu hoch (num:=high(VBilArray)
   BlockWrite(fil,num,sizeof(num));                  
   for i:=0 to high(VBilArray) do
...
...

...
procedure TForm1.ReadFile(filename:string);
var   fil:   file;
        i:     integer;
        num:   byte;    {allows up to 65535 records}
ver:   byte;

   function ReadString:ShortString;
    begin  {ReadString}
      BlockRead(fil,result,1);              {Read the length of the string}
      BlockRead(fil,result[1],length(result));      //<-Danke Dir,himitsu
    end;  {ReadString}
...
...
  SetLength(VBilArray,num);
Label7.Caption:='in ReadFile: '+'Num: '+inttostr(num)+
'HighVBilArray: '+inttostr(High(VBilArray));
   for i:=0 to num-1 do                             //<- num-1 sonst ERROR
...
...


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:04 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz