Casady
Casady

Reputation: 1456

Saving a string with null characters to a file

I have a string that contains null characters.

I've tried to save it to a file with this code:

myStringList.Text := myString;
myStringList.SaveToFile('c:\myfile');

Unfortunately myStringList.Text is empty if the source string has a null character at the beginning.

I thought only C string were terminated by a null character, and Delphi was always fine with it.

How to save the content of the string to a file?

Upvotes: 1

Views: 2043

Answers (3)

David Heffernan
David Heffernan

Reputation: 613572

When you set the Text property of a TStrings object, the new value is parsed as a null-terminated string. Therefore when the code reaches your null character, the parsing stops.

I'm not sure why the Delphi RTL code was designed that way, and its not documented, but that's just how setting the Text property works.

You can avoid this by using the Add method rather than the Text property.

myStringList.Clear;
myStringList.Add(myString);
myStringList.SaveToFile(FileName);

Upvotes: 5

Wouter van Nifterick
Wouter van Nifterick

Reputation: 24116

About writing strings to a file in general.. I still see people creating streams or stringlists just to write some stuff to a file, and then destroy the stream or stringlist.

Delphi7 didn't have IOUtuls.pas yet, but you're missing out on that.

There's a handy TFile record with class methods that lets you write text to a file with a single line, without requiring temporary variables:

TFile.WriteAllText('out.txt','hi');

Upgrading makes your life as a Delphi developer a lot easier. This is just a tiny example.

Upvotes: 3

Ken White
Ken White

Reputation: 125757

I think you mean "save a string that has #0 characters in it".

If that's the case, don't try and put it in a TStringList. In fact, don't try to save it as a string at all; just like in C, a NULL character (#0 in Delphi) causes the string to be truncated at times. Use a TFileStream and write it directly as byte content:

var
  FS: TFileStream;
begin
  FS := TFileStream.Create('C:\MyFile', fmCreate);
  try
    FS.Write(myString[1], Length(myString) * SizeOf(Char));
  finally
    FS.Free;
  end;
end;

To read it back:

var
  FS: TFileStream;
begin
  FS := TFileStream.Create('C:\MyFile', fmOpenRead);
  try
    SetLength(MyString, FS.Size);
    FS.Read(MyString[1], FS.Size);
  finally
    FS.Free;
  end;
end;

Upvotes: 6

Related Questions