Kristian Sander
Kristian Sander

Reputation: 291

TFileStream behaves very strange

I have this code unit: (I run Delphi 7 on an Win XP sp 3).

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

CONST
   EOL = #13#10;

type
  TForm1 = class(TForm)
    Button1: TButton;

    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    Procedure StringToStream(Ofile : TFileStream; Const StrValue : String);

  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1   : TForm1;
  Curdir  : String;
  Ofile   : TFileStream;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
   Ofile := TFileStream.Create(curdir + '\TESTfil.HTML', fmCreate,fmsharedenynone);
   try
      StringToStream(Ofile, '<HTML><BODY> </BODY></HTML>' + EOL);
//      StringToStream(Ofile, '</BODY></HTML>' + EOL);
   finally
      Ofile.Free;
   end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
   Curdir := ExtractFileDir(Application.ExeName);
end;

Procedure Tform1.StringToStream(Ofile : TFileStream; Const StrValue : String);

BEGIN
   IF length(StrValue) > 0 then
      Ofile.Write(StrValue,length(StrValue));
    Ofile.Write('testpunkt',9);

END; 

And the output of this unit is:

"28 non printable characters" + "\testpunkt" 

I have tried to make the string a "CONST" . --> same error

I have tried it with PCHAR's -- got a lot of errors ... (mostly syntax errors)

I have changed INDY7 to INDY9 to get idGlobal.WriteStringtoStream() - but that particular INDY-9 does not support WriteStringToStream .

What am I doing wrong ?

Upvotes: 3

Views: 162

Answers (1)

David Heffernan
David Heffernan

Reputation: 612794

You have written the address of the string rather than its contents. To write a string to a stream use this code:

procedure TForm1.StringToStream(Ofile: TFileStream; const StrValue: string);
begin
  Ofile.WriteBuffer(Pointer(StrValue)^, Length(StrValue));
end; 

Here I have dereferenced the pointer and so written the content of the string.

Notes:

  • This code does not need to check for the string being empty.
  • Since you use Delphi 7 and strings are ANSI, it is reasonable to pass Length(StrValue). If you ever move to Unicode then you would have to modify the code to address encoding.
  • I use WriteBuffer rather than Write because the former will raise an exception in case of an error, in contrast to Write.
  • Your code assumes that it is safe to write to the same directory as the executable. That assumption is likely to break down if ever you deploy your program.
  • Your use of global variables is just setting you up for a fall. See to use local variables where possible, variables passed as parameters, data members of classes. Shun globals.
  • Writing XML is fraught with complication. Attempting to do so using raw string operations will likely lead to many problems with encoding, at some point in the future. A wise move would be to use an XML library now so that you don't have to re-write your code in the future.

Upvotes: 5

Related Questions