AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

TFileStream Problem

Ein Thema von kurtm1 · begonnen am 10. Jul 2005 · letzter Beitrag vom 10. Jul 2005
Antwort Antwort
kurtm1

Registriert seit: 13. Dez 2003
348 Beiträge
 
#1

TFileStream Problem

  Alt 10. Jul 2005, 12:23
Ich glaube ich bin gerade unfähig:
Ich möchte eine String Variable ganz normal abspeichern (mittels TFilestream)

Delphi-Quellcode:
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;
und einlesen mache ich so:
Delphi-Quellcode:
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;
Kann wir wer sagen, wo der Fehler liegt?
  Mit Zitat antworten Zitat
Benutzerbild von Jens Schumann
Jens Schumann

Registriert seit: 27. Apr 2003
Ort: Bad Honnef
1.644 Beiträge
 
Delphi 2009 Professional
 
#2

Re: TFileStream Problem

  Alt 10. Jul 2005, 12:32
Hallo,
es handelt sich eigentlich nicht um einen Fehler. Die Huge-Strings sind hier Schuld.
Delphi-Quellcode:
var
  ini : String;
...
  SizeOf(ini); // liefert als Ergebnis 4.
..
in der Variablen ini ist nur eine Referenz (Zeiger) auf den String gespeichert.
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.
I come from outer space to save the human race
  Mit Zitat antworten Zitat
Benutzerbild von Taladan
Taladan

Registriert seit: 5. Aug 2003
Ort: Osnabrück
505 Beiträge
 
Delphi 2005 Professional
 
#3

Re: TFileStream Problem

  Alt 10. Jul 2005, 12:35
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:
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;
und einlesen mache ich so:
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;
Marco
Wer Rechtschreibfehler findet, der darf sie behalten

Carpe Diem - Nutze den Tag (und zwar den ganzen!)
  Mit Zitat antworten Zitat
Christian Seehase
(Co-Admin)

Registriert seit: 29. Mai 2002
Ort: Hamburg
11.116 Beiträge
 
Delphi 11 Alexandria
 
#4

Re: TFileStream Problem

  Alt 10. Jul 2005, 12:47
Moin Taladan,

Zitat von Taladan:
Daher mußte die Länge der Datei mit abspeichern.
wozu dass?
TFileStream enthält doch die Eigenschaft Size.

@Jens:
Statt PChar(Stringvariable)^ kann man auch einfach Stringvariable[1] schreiben.
Tschüss Chris
Die drei Feinde des Programmierers: Sonne, Frischluft und dieses unerträgliche Gebrüll der Vögel.
Der Klügere gibt solange nach bis er der Dumme ist
  Mit Zitat antworten Zitat
kurtm1

Registriert seit: 13. Dez 2003
348 Beiträge
 
#5

Re: TFileStream Problem

  Alt 10. Jul 2005, 12:50
Zitat von Christian Seehase:
Moin Taladan,

wozu dass?
TFileStream enthält doch die Eigenschaft Size.
das frage ich mich auch
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#6

Re: TFileStream Problem

  Alt 10. Jul 2005, 13:03
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
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#7

Re: TFileStream Problem

  Alt 10. Jul 2005, 13:04
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:
var LLen: Integer;
begin
  [...]
  LLen := Length(ini);
  Settings.Write(LLen, SizeOf(LLen));
  Settings.Write(ini[1],LLen);
  [..]
zum Lesen
Delphi-Quellcode:
var LLen: Integer;
begin
  [...]
  Settings.Read(LLen, SizeOf(LLen));
  SetLength(ini);
  Settings.Read(ini[1],LLen);
  [..]
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Benutzerbild von Sprint
Sprint

Registriert seit: 18. Aug 2004
Ort: Edewecht
712 Beiträge
 
Delphi 5 Professional
 
#8

Re: TFileStream Problem

  Alt 10. Jul 2005, 13:13
Zitat von kurtm1:
Ich möchte eine String Variable ganz normal abspeichern (mittels TFilestream)
Mit TFileStream:
Delphi-Quellcode:
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;
Ich würde es aber ohne TFileStream machen:
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;
Ciao, Sprint.

"I don't know what I am doing, but I am sure I am having fun!"
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#9

Re: TFileStream Problem

  Alt 10. Jul 2005, 13:15
@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
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
kurtm1

Registriert seit: 13. Dez 2003
348 Beiträge
 
#10

Re: TFileStream Problem

  Alt 10. Jul 2005, 15:31
k danke, habs jetzt mit euren Lösungen geschafft
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:02 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