![]() |
TFileStream Problem
Ich glaube ich bin gerade unfähig:
Ich möchte eine String Variable ganz normal abspeichern (mittels TFilestream)
Delphi-Quellcode:
und einlesen mache ich so:
var Settings:TFileStream;
var ini:String; [..] if not FileExists('settings.txt') then Settings:=TFileStream.Create('settings.txt', fmcreate) else Settings:=TFileStream.Create('settings.txt', fmopenwrite); Settings.Write(ini,sizeof(ini)); Settings.Free;
Delphi-Quellcode:
Kann wir wer sagen, wo der Fehler liegt?
var Settings:TFileStream;
var str:String; [..] if not FileExists('settings.txt') then ShowMessage('Keine Preset Datei gefunden') else begin Settings:=TFileStream.Create('settings.txt', fmopenread); Settings.Read(str,sizeof(settings)); Settings.Free; end; |
Re: TFileStream Problem
Hallo,
es handelt sich eigentlich nicht um einen Fehler. Die Huge-Strings sind hier Schuld.
Delphi-Quellcode:
in der Variablen ini ist nur eine Referenz (Zeiger) auf den String gespeichert.
var
ini : String; ... SizeOf(ini); // liefert als Ergebnis 4. .. Deshalb musst beim Schreiben und Lesen von Strings in einen Stream wie folgt vorgehen. D.h. ich habe mir mal zwei Streamnachfahren gebastelt
Delphi-Quellcode:
interface
uses Sysutils, Classes; Type TMemoryStreamExt = class(TMemoryStream) public procedure WriteStringToStream(aStr : String); function ReadStringFromStream : String; end; TFileStreamExt = class(TFilestream) public procedure WriteStringToStream(aStr : String); function ReadStringFromStream : String; end; implementation { TFileStreamExt } procedure TFileStreamExt.WriteStringToStream(aStr : String); var aStrLen : Integer; begin aStrLen:=Length(aStr); // Länge des Strings holen WriteBuffer(aStrLen,SizeOf(Integer)); // Länge des Strings in den Stream schreiben WriteBuffer(Pointer(aStr)^,aStrLen); // Den eigentlichen String in den Stream schieben end; function TFileStreamExt.ReadStringFromStream: String; var aStrLen : Integer; begin ReadBuffer(aStrLen,SizeOf(Integer)); // Länge des Strings aus Stream lesen SetLength(Result,aStrLen); // Länge des Strinsg setzen ReadBuffer(Pointer(Result)^,aStrLen); // Stringdaten aus Stream lesen end; { TMemoryStreamExt } function TMemoryStreamExt.ReadStringFromStream: String; var aStrLen : Integer; begin ReadBuffer(aStrLen,SizeOf(Integer)); SetLength(Result,aStrLen); ReadBuffer(Pointer(Result)^,aStrLen); end; procedure TMemoryStreamExt.WriteStringToStream(aStr: String); var aStrLen : Integer; begin aStrLen:=Length(aStr); WriteBuffer(aStrLen,SizeOf(Integer)); WriteBuffer(Pointer(aStr)^,aStrLen); end; end. |
Re: TFileStream Problem
Bei einer nicht bekannten Datei, weiß er natürlich nicht, wie viel er auslesen soll, da dieser Eert beim start ja noch auf Null steht. Daher mußte die Länge der Datei mit abspeichern.
Delphi-Quellcode:
und einlesen mache ich so:
var Settings:TFileStream;
var ini:String; var length : integer; [..] if not FileExists('settings.txt') then Settings:=TFileStream.Create('settings.txt', fmcreate) else Settings:=TFileStream.Create('settings.txt', fmopenwrite); length := sizeof(ini); Settings.Write(length, sizeof(length)); Settings.Write(ini,i); Settings.Free;
Delphi-Quellcode:
var Settings:TFileStream;
var str:String; var length: integer; [..] if not FileExists('settings.txt') then ShowMessage('Keine Preset Datei gefunden') else begin Settings:=TFileStream.Create('settings.txt', fmopenread); settings.read(length, sizeof(length)); Settings.Read(str,length); Settings.Free; end; |
Re: TFileStream Problem
Moin Taladan,
Zitat:
TFileStream enthält doch die Eigenschaft Size. @Jens: Statt PChar(Stringvariable)^ kann man auch einfach Stringvariable[1] schreiben. |
Re: TFileStream Problem
Zitat:
|
Re: TFileStream Problem
Taladan hat sich gewiss überlegt, dass ein file stream für nur einen string eher selten ist. Speichert man aber mehrere strings in einem stream, dann ist es best practice die einzelnen string Längen voran zu speichern, damit die buffer allocation beim Einlesen optimal unterstützt werden kann.
Grüße vom marabu |
Re: TFileStream Problem
Ist euch eventuell schonmal in den Sinn gekommen das mann mehre Strings in eine Datei schreiben will? Und in so einem Fall nützt mir TFileStream.Size reichlich wenig weil ich anhand der gesamtgröße nicht weiß wo welcher String aufhört!
Zur Ausgangsfrage: Wenn ein String geschrieben werden soll dann musst du das erste Zeischen angeben. Und anstelle von SizeOf solltest du bei Strings "Length" verwenden. Zu Schreiben
Delphi-Quellcode:
zum Lesen
var LLen: Integer;
begin [...] LLen := Length(ini); Settings.Write(LLen, SizeOf(LLen)); Settings.Write(ini[1],LLen); [..]
Delphi-Quellcode:
var LLen: Integer;
begin [...] Settings.Read(LLen, SizeOf(LLen)); SetLength(ini); Settings.Read(ini[1],LLen); [..] |
Re: TFileStream Problem
Zitat:
Delphi-Quellcode:
Ich würde es aber ohne TFileStream machen:
procedure WriteStringToFile(const FileName, S: String);
begin try with TFileStream.Create(FileName, fmCreate) do try if Length(S) > 0 then WriteBuffer(S[1], Length(S)); finally Free; end; except end; end; procedure ReadStringFromFile(const FileName: String; var S: String); begin SetLength(S, 0); try with TFileStream.Create(FileName, fmOpenRead) do try if Size > 0 then begin SetLength(S, Size); ReadBuffer(S[1], Size); end; finally Free; end; except end; end;
Delphi-Quellcode:
procedure WriteStringToFile(const FileName, S: String);
var Handle: Integer; begin Handle := FileCreate(FileName); if Handle <> -1 then begin if Length(S) > 0 then FileWrite(Handle, S[1], Length(S)); FileClose(Handle); end; end; procedure ReadStringFromFile(const FileName: String; var S: String); var Handle: Integer; Size: Integer; begin SetLength(S, 0); Handle := FileOpen(FileName, fmOpenRead); if Handle <> -1 then begin Size := FileSeek(Handle, 0, soFromEnd); if Size > 0 then begin SetLength(S, Size); FileSeek(Handle, 0, soFromBeginning); FileRead(Handle, S[1], Size); end; FileClose(Handle); end; end; |
Re: TFileStream Problem
@sprint: deine Variante hat auch was für sich, aber ich finds schon gut das er TFileStream nimmt und sich somit gleich mit den Objecten beschäftigt anstelle von globalen Funktionen
|
Re: TFileStream Problem
k danke, habs jetzt mit euren Lösungen geschafft
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:55 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