Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Dynamisches Array aus Filestream lesen ? (https://www.delphipraxis.net/91649-dynamisches-array-aus-filestream-lesen.html)

malte_M 8. Mai 2007 09:46


Dynamisches Array aus Filestream lesen ?
 
Hallo,
ich habe schon wieder ein Problem.

Ich speichere mit folgender Methode ein dynamisches Array in eine Datei via TFilestream

Delphi-Quellcode:
type
  TMyRecord = Record
    channel:Byte;
    duration:Integer;
 end;

Var
 bwl1 : Array of TMyRecord;

//Hier wird dann damit gearbeitet

Procedure SaveToFile;
var
  f: TFileStream;
  i: integer;
begin
  f := TFileStream.Create(ExtractFilePath(Paramstr(0))+'iv1.dat',fmCreate);
  try
    for i := 0 to high(bwl1) do
      f.write(bwl1[i],sizeOf(TMyRecord));
  finally
    f.free;
  end;
end;
Ob der Code funktioniert, weis ich nicht, weil ich es nicht hinbekomme die Daten wieder in ein Array einzulesen.

Kann mir jemand einen Tipp geben, wie ich das machen kann?

Gruß Malte

Muetze1 8. Mai 2007 10:07

Re: Dynamisches Array aus Filestream lesen ?
 
Na und wie hast du es denn bisher versucht? Wodran ist es denn gescheitert? Fehlermeldungen? Welche?

Muss man wirklich alles nachfragen oder hoffst du wirklich auf fertigen Quelltext ohne Lerneffekt?

SirThornberry 8. Mai 2007 10:11

Re: Dynamisches Array aus Filestream lesen ?
 
laut quelltext wird das ganze richtig gespeichert. Allerdings gehts auch etwas fixer
Delphi-Quellcode:
f := TFileStream.Create(ExtractFilePath(Paramstr(0))+'iv1.dat',fmCreate);
try
  f.write(bwll[0], SizeOf(TMyRecord) * Length(bwll));
finally
  f.free;
end;

malte_M 8. Mai 2007 10:19

Re: Dynamisches Array aus Filestream lesen ?
 
Wenn ich auf fertigen Quellcode gehofft hätte, hätte ich wohl nicht um einen Tipp sondern um Code gebeten.

Mein letzter Versuch sieht so aus:

Delphi-Quellcode:
Procedure LoadfromFile;
var
  f: TFileStream;
  i: integer;
begin
  i:=0;
  f := TFileStream.Create(ExtractFilePath(Paramstr(0))+'iv1.dat',fmOpenRead);
  f.position:=0;
  try
   while not eof do
   begin
     SetLength(bwl1,length(bwl1)+1);
     f.Read(bwl1[i].channel,1); // Channel Byte 1 Byte groß
     f.Read(bwl1[i].duration,4); // duration Integer 4 Byte groß
     inc(i,5);
     f.position:=i;
   end;
  finally
   f.Free;
  end;
 { }
end;
Die meisten meiner Versuche endeten mit einem I/O Error 6 oder Schtuzverletzungen

Dezipaitor 8. Mai 2007 10:35

Re: Dynamisches Array aus Filestream lesen ?
 
du solltest auch noch vorher speichern, wieviele Elemente der Array hat,
sonst kannst du kein SetLength verwenden.

Außerdem bringt das EOF meiner Ansicht nach nichts.

malte_M 8. Mai 2007 10:42

Re: Dynamisches Array aus Filestream lesen ?
 
Hallo,

du hast Recht. EOF ist für den I/O Error 6 verantwortlich, soviel habe ich schon rausgefunden. Die Anzahl der Elemente läßt sich aber leicht errechnen. Größe des Streams durch Größe eines Records.

Zumindest das funktioniert. Aber nun bin ich wieder bei Schutzverletzungen angelangt.

Muetze1 8. Mai 2007 10:52

Re: Dynamisches Array aus Filestream lesen ?
 
Zitat:

Zitat von malte_M
EOF ist für den I/O Error 6 verantwortlich, soviel habe ich schon rausgefunden. Die Anzahl der Elemente läßt sich aber leicht errechnen. Größe des Streams durch Größe eines Records.

Dann mach das auch.

Hier noch ein paar Kommentare:
Delphi-Quellcode:
Procedure LoadfromFile;
var
  f: TFileStream;
  i: integer;
begin
  i:=0;
  f := TFileStream.Create(ExtractFilePath(Paramstr(0))+'iv1.dat',fmOpenRead);
  f.position:=0;  // unnötig, nach dem Öffnen ist er immer bei 0
  try
   while not eof do // was ist eof? wo definiert? TFileStream hat keine solche Eigenschaft (du greifst nichtmal auf TFileStream zu)
   begin
     SetLength(bwl1,length(bwl1)+1);  // wenn du das berechnen kannst aus der Grösse der Datei, dann mach das einmalig vorher.
     f.Read(bwl1[i].channel,1);       // wenn du das ganze schreibst, dann schreibst du den Record auf einmal, warum
     f.Read(bwl1[i].duration,4);      // liest du ihn dann hier auf einmal in Einzelteilen? Grund?
     inc(i,5);                        // Warum das? Warum springst du im Array gleich 5 Indexe weiter anstatt einfach Record um Record einzulesen?
     f.position:=i;                   // Wozu? Beim Schreiben setzt du den Dateizeiger auch nicht mit jedem Record weiter - warum sollte es also beim Lesen erforderlich sein?
   end;
  finally
   f.Free;
  end;
{ }
end;

Udontknow 8. Mai 2007 11:09

Re: Dynamisches Array aus Filestream lesen ?
 
Hallo!

Ein paar Tipps:

Immer ReadBuffer und WriteBuffer anstelle von Read und Write verwenden, damit ist man ein wenig sicherer, was Fehlervermeidung angeht.
Die Größe des Arrays würde ich zu Anfang in den Stream schreiben. Du kannst dann später nämlich auch noch weitere Informationen in die Datei schreiben, die nicht zum Array gehören.
Den Code zum Lesen und Schreiben des Streams würde ich in Routinen LoadFromStream und SaveToStream auslagern und diese dann von LoadFromFile/SaveToFile aufrufen lassen. So kannst du später die Datenquellen ganz leicht ändern, z.B. plötzlich von einem TCP-Server einen Array abholen etc...

Hier ein bisserl Code:

Delphi-Quellcode:
procedure LoadFromStream(Stream:TStream);
var i,count:Integer;
begin
  //Anzahl der Elemente auslesen
  Stream.ReadBuffer(count,SizeOf(count));

  //Array-Länge setzen
  SetLength(bwl1,count);
 
  //Record-Daten aus Stream lesen
  for i:=0 to count-1 do
    Stream.ReadBuffer(bwl1[i],SizeOf(bwl1[i]));
end;

procedure LoadFromFile(FileName:String);
var
  f: TFileStream;
begin
  f := TFileStream.Create(FileName,fmOpenRead);
  try
    LoadFromStream(f);
  finally
    f.Free;
  end;
end;
Die Speicherroutinen müssen analog aufgebaut werden (also erst Anzahl der Elemente als Integer schreiben, dann die einzelnen Records).

Cu,
Udontknow

malte_M 8. Mai 2007 11:34

Re: Dynamisches Array aus Filestream lesen ?
 
Danke Udontknow,

jetzt hab ich es hinbekommen.Das mit dem auslagern werde ich machen. Hört sich logisch an. Allerdings nur, weil ich 5 Array speichern und laden möchte. Von TCP Servern werde ich erstmal die Finger lassen. :lol: Dazu sollte ich wohl etwas mehr als meine zwei Wochen Erfahrung mitbringen.

Danke nochmal

cu
Malte


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:33 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