![]() |
"Stream Lesefehler" bei Laden via TFileStream
Liste der Anhänge anzeigen (Anzahl: 2)
Hallo :)
Ich habe 2 Objeke, ein Item und eine ItemList. Das Item ist wie folgt aufgebaut
Delphi-Quellcode:
Und die ItemList ist eine ganze Klasse, die ein array of TItem hat und dieses dann mit entsprechenden Methoden verwaltet.
TItem = record
ID: Integer; // wird automatisch gesetzt Name: String; Info: String; end; // TItem Weiterhin habe ich eine Klasse TListHandler, da ich die ItemList in mehreren Forms brauche. Der Listhandler hat auch die Save und Load Methoden. Bei denen mache ich dann offensichtlich etwas falsch: (lngth ist die Länge des Dynmaischen arrays, die ich in einer seperaten Datei (ListenName.list~) speichere :D)
Delphi-Quellcode:
Anbei (falls notwendig) noch die beiden Klassen TItemList und TListHandler
// Load a existing List from a specific Filepath
function TListHandler.Load(const FilePath, Pathlngth: string): TItemList; var F_Stream: TFileStream; F_tmp: TFileStream; i: Integer; lngth: Integer; Name, Info: String; begin try F_Stream := TFileStream.Create(FilePath, fmOpenRead); F_tmp := TFileStream.Create(Pathlngth, fmOpenRead); F_tmp.ReadBuffer(lngth, SizeOf(lngth)); for i := 0 to lngth-1 do begin Name := List.Item[i].Name; Info := List.Item[i].Info; F_Stream.ReadBuffer(Name[1], SizeOf(Name)); F_Stream.ReadBuffer(Info[1], SizeOf(Info)); List.Length := lngth; end; finally F_Stream.Free; F_tmp.Free; end; // if end; // Load //############################################################################## // Save the whole List as it is to a pre-specified Filepath procedure TListHandler.Save(const FilePath, Pathlngth: String); var FileStream: TFileStream; F_tmp: TFileStream; i: Integer; lngth: Integer; Name, Info: String; begin try FileStream := TFileStream.Create(FilePath, fmCreate); F_tmp := TFileStream.Create(Pathlngth, fmCreate); lngth := List.Length; F_tmp.WriteBuffer(lngth, SizeOf(lngth)); for i := 0 to List.Length-1 do begin Name := List.Item[i].Name; Info := List.Item[i].Info; FileStream.WriteBuffer(Name[1], SizeOf(Name)); FileStream.WriteBuffer(Info[1], SizeOF(Info)); end; finally FileStream.Free; F_tmp.Free; end; // finally end; // Save PS: Beide Klassen sind noch nicht fertig und entsprechende Methoden werden im letzten Zug ausgelagert. :wink: |
AW: "Stream Lesefehler" bei Laden via TFileStream
Wenn Du Strings in einem Stream speichern willst, musst Du dir vorher die Länge mit ablegen. Da die Strings unterschiedlich lang sein können, je nachdem, was eingeben wurde.
Ich habe dafür solche Funktionen:
Delphi-Quellcode:
Anders wäre es bei ShortString, der String ist dann immer 255 Zeichen lang, diesen könntest Du ohne vorheriges Abspeichern der Länge lesen und schreiben
procedure WriteStringToStream(stream : TStream; str : String);
var strLength : integer; begin strLength:=length(str); stream.Write(strLength,SizeOf(strLength)); if strLength>0 then stream.Write(str[1],strLength*SizeOf(str[1])); end; function ReadStringFromStream(stream : TStream) : String; var strLength : integer; hs : String; begin result:=''; stream.read(strLength,SizeOf(strLength)); if strLength>0 then begin hs := ''; SetLength(hs,strLength); stream.read(hs[1],strLength*SizeOf(hs[1])); result:=hs; end; end; |
AW: "Stream Lesefehler" bei Laden via TFileStream
Hallo,
du kannst auch mal einen Blick auf TWriter und TReader werfen, die haben für unterschiedliche Typen entsprechende Routinen an Bord. Gruß Frank |
AW: "Stream Lesefehler" bei Laden via TFileStream
Und der Stream-Fehler ist vollkommen verständlich.
Denn da ist alles falsch, was man nur falsch machen kann. In Load: - Wann wurde die größe der Liste "List" gesetzt? - Wann wurde die Länge der Strings "Name" und "Info" gesetz? - SizeOf(Name) gibt die größe des internen String-Pointers zurück. Beim Debuggen hätte dir auffallen müssen, daß 4 Byte garantiert nicht korrekt sein können. - uvm. |
AW: "Stream Lesefehler" bei Laden via TFileStream
Okay ... ich hab das glaube ich immernoch nicht so ganz verstanden.
(Ihr müsst das entschuldigen, ich arbeite das erste Mal mit FileStreams und mein Programmierlehrer kann das nur in C#, nicht in Delphi x.x) Habe die Save/Load mal wie folgt angepasst, aber irgendwie steht in den Variablen Name und Info beim Laden nurnoch müll ...
Delphi-Quellcode:
// Load a existing List from a specific Filepath
procedure TListHandler.Load(const FilePath: String); var F_Stream: TFileStream; lngth: Integer; strlngth: Integer; I: Integer; name, Info: String; begin try F_Stream := TFileStream.Create(FilePath, fmOpenRead); F_Stream.ReadBuffer(lngth, SizeOf(lngth)); List.Length := lngth; for I := 0 to List.Length - 1 do begin F_Stream.ReadBuffer(strlngth, SizeOf(strlngth)); SetLength(Name, strlngth); F_Stream.ReadBuffer(Name[1], strlngth*SizeOf(Name[1])); List.Item[i].Name := Name; F_Stream.ReadBuffer(lngth, SizeOf(lngth)); SetLength(Info, lngth); F_Stream.ReadBuffer(Info[1], strlngth*SizeOf(Info[1])); List.Item[i].Info := Info; F_Stream.ReadBuffer(lngth, SizeOf(lngth)); List.Item[i].ID := lngth; end;// for finally F_Stream.Free; end; // finally end; // Load // ############################################################################# // Save the whole List as it is to a pre-specified Filepath procedure TListHandler.Save(const FilePath: String); var F_Stream: TFileStream; lngth: Integer; strLngth: Integer; I: Integer; begin try F_Stream := TFileStream.Create(FilePath, fmCreate); lngth := List.Length; F_Stream.WriteBuffer(lngth, SizeOf(lngth)); for I := 0 to List.Length - 1 do begin strlngth := Length(List.Item[I].Name); F_Stream.WriteBuffer(strlngth, SizeOf(strlngth)); F_Stream.WriteBuffer(List.Item[I].Name[1], strlngth*SizeOf(List.Item[I].Name[1])); strlngth := Length(List.Item[i].Info); F_Stream.WriteBuffer(strlngth, SizeOf(strlngth)); F_Stream.WriteBuffer(List.Item[I].Info[1], strlngth*SizeOf(List.Item[I].Info[1])); lngth := List.Item[i].ID; F_Stream.WriteBuffer(strlngth, SizeOf(strlngth)); end; // for finally F_Stream.Free; end; end; // Save |
AW: "Stream Lesefehler" bei Laden via TFileStream
Ich sehe auf Anhieb keine Fehler.
Ich gehe aber aus, dass der Fehler evt. in der Load Methode liegt:
Delphi-Quellcode:
Ist Length ein Property? Falls nicht -> Fehlerquelle!
// load
List.Length := lngth; Setzt der Setter von Length die Arraygröße - Falls nicht -> Fehlerquelle! |
AW: "Stream Lesefehler" bei Laden via TFileStream
Zitat:
Delphi-Quellcode:
property Length: Integer read Get_Length write Set_Length;
und ... :
Delphi-Quellcode:
function TItemList.Get_Length: Integer;
begin // Dynamic arrays are zero-based ! Result := High(ItemList) + 1; end; procedure TItemList.Set_Length(const New_Length: Integer); begin SetLength(ItemList, New_Length); end; |
AW: "Stream Lesefehler" bei Laden via TFileStream
Wenn Du Delphi 2009 + hast solltest Du spätestens von
Bytes = Length(String)* SizeOf(Char) ausgehen. |
AW: "Stream Lesefehler" bei Laden via TFileStream
Zitat:
Delphi-Quellcode:
strlngth := Length(List.Item[i].Info); // <-------- Length(String)
F_Stream.WriteBuffer(strlngth, SizeOf(strlngth)); F_Stream.WriteBuffer(List.Item[I].Info[1], strlngth*SizeOf(List.Item[I].Info[1])); // <-------- Length(String) * SizeOf(Char) |
AW: "Stream Lesefehler" bei Laden via TFileStream
beim schreiben ...
|
AW: "Stream Lesefehler" bei Laden via TFileStream
Vielen Dank nochmal an alle und @Bummi
Das mache ich doch schon sowohl beim Schreiben als auch beim Lesen. :) Das war nicht das Problem. Habe den Fehler nun gefunden (habe einmal strlngth und lngth vertauscht). Mit dem Code hier geht es jetzt:
Delphi-Quellcode:
procedure TListHandler.Load(const FilePath: String);
var F_Stream: TFileStream; lngth: Integer; strlngth: Integer; I: Integer; name, Info: String; begin try F_Stream := TFileStream.Create(FilePath, fmOpenRead); F_Stream.ReadBuffer(lngth, SizeOf(lngth)); List.Length := lngth; for I := 0 to List.Length - 1 do begin F_Stream.ReadBuffer(strlngth, SizeOf(strlngth)); SetLength(Name, strlngth); F_Stream.ReadBuffer(Name[1], strlngth*SizeOf(Name[1])); Item.Name := Name; F_Stream.ReadBuffer(strlngth, SizeOf(lngth)); SetLength(Info, strlngth); F_Stream.ReadBuffer(Info[1], strlngth*SizeOf(Info[1])); Item.Info := Info; F_Stream.ReadBuffer(lngth, SizeOf(lngth)); Item.ID := lngth; List.Item[i] := Item; end;// for finally F_Stream.Free; end; // finally end; // Load // ############################################################################# // Save the whole List as it is to a pre-specified Filepath procedure TListHandler.Save(const FilePath: String); var F_Stream: TFileStream; lngth: Integer; strLngth: Integer; I: Integer; begin try F_Stream := TFileStream.Create(FilePath, fmCreate); lngth := List.Length; F_Stream.WriteBuffer(lngth, SizeOf(lngth)); for I := 0 to List.Length - 1 do begin strlngth := Length(List.Item[I].Name); F_Stream.WriteBuffer(strlngth, SizeOf(strlngth)); F_Stream.WriteBuffer(List.Item[I].Name[1], strlngth*SizeOf(List.Item[I].Name[1])); strlngth := Length(List.Item[i].Info); F_Stream.WriteBuffer(strlngth, SizeOf(strlngth)); F_Stream.WriteBuffer(List.Item[I].Info[1], strlngth*SizeOf(List.Item[I].Info[1])); lngth := List.Item[i].ID; F_Stream.WriteBuffer(lngth, SizeOf(lngth)); end; // for finally F_Stream.Free; end; end; // Save Vielen Dank nochmals an alle :) Ihr habt mir sehr geholfen :thumb: Hier kann nun also geschlossen werden ^^ |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:18 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz