Writing a string to a TFileStream in Delphi 2010

36,066

Solution 1

You don't need a separate buffer to write a string to a stream. Probably the simplest way to do it is to encode the string to UTF8, like so:

procedure TStreamEx.writeString(const data: string);
var
   len: cardinal;
   oString: UTF8String;
begin
   oString := UTF8String(data);
   len := length(oString);
   self.WriteBuffer(len, 4);
   if len > 0 then
      self.WriteBuffer(oString[1], len);
end;

function TStreamEx.readString: string;
var
   len: integer;
   iString: UTF8String;
begin
   self.readBuffer(len, 4);
   if len > 0 then
   begin
      setLength(iString, len);
      self.ReadBuffer(iString[1], len);
      result := string(iString);
   end;
end;

I've declared TStreamEx as a class helper for TStream, but it shouldn't be too difficult to rewrite these as a solo procedure and function like your example.

Solution 2

Delphi 2010 has a nice solution for this, documented here:

http://docwiki.embarcadero.com/CodeExamples/en/StreamStrRdWr_%28Delphi%29

var
  Writer: TStreamWriter;
...

  { Create a new stream writer directly. }
  Writer := TStreamWriter.Create('MyFile.txt', false, TEncoding.UTF8);
  Writer.Write('Some Text');

  { Close and free the writer. }
  Writer.Free();
Share:
36,066
JosephStyons
Author by

JosephStyons

I started out as a professional developer using Delphi and Oracle in a Win32 client-server environment for a manufacturing company. I worked for five years in consulting, implementing solutions for dozens of clients and using many disparate technologies. Since then, I've worked for and with the non-profit industry, building applications that help them move their missions forward. My bread-and-butter is VB.NET and C# against a SQL Server back-end using a SOA architecture. But I can and will use whatever tool gets the job done, and I've had fun doing so with Angular, jQuery, ASP.NET, PHP, and even my own homemade frameworks to deliver solutions against that platform.

Updated on June 04, 2020

Comments

  • JosephStyons
    JosephStyons almost 4 years

    I have Delphi 2007 code that looks like this:

    procedure WriteString(Stream: TFileStream; var SourceBuffer: PChar; s: string);
    begin
      StrPCopy(SourceBuffer,s);
      Stream.Write(SourceBuffer[0], StrLen(SourceBuffer));
    end;
    

    I call it like this:

    var
      SourceBuffer : PChar;
      MyFile: TFileStream;
    
    ....
    
    SourceBuffer := StrAlloc(1024);
    MyFile := TFileStream.Create('MyFile.txt',fmCreate);
    WriteString(MyFile,SourceBuffer,'Some Text');
    ....
    

    This worked in Delphi 2007, but it gives me a lot of junk characters in Delphi 2010. I know this is due to unicode compliance issues, but I am not sure how to address the issue.

    Here is what I've tried so far:

    • Change the data type of SourceBuffer(and also the parameter expected by WideString) to PWideChar

    • Every one of the suggestions listed here

    What am I doing wrong?

  • JosephStyons
    JosephStyons over 14 years
    This worked for me after I removed the "self.WriteBuffer(len, 4);" - that was writing some gibberish characters to the output file.
  • Mason Wheeler
    Mason Wheeler over 14 years
    Those "gibberish characters" are the length of the string, so the reading function knows how much to read back in. If you need this to be plain text, you'll need some other way to tell readString where to stop.
  • JosephStyons
    JosephStyons over 14 years
    I am writing this file out for another application to read it in, so it is not important that I be able to read it back in.
  • Mason Wheeler
    Mason Wheeler over 14 years
    In that case, make sure that the other application knows it's receiving a string in UTF8 format. Or if you don't have control over the other app, convert it to an AnsiString instead of a UTF8String. But you could lose data doing that if you're using Unicode characters outside the ANSI set.
  • jonjbar
    jonjbar about 13 years
    Link is broken. Looks like this one: docwiki.embarcadero.com/CodeExamples/en/…
  • John Kaster
    John Kaster about 13 years
    John, thanks for the correction to the link. Looks like a violation of the golden rule for websites - never break a permalink. Particularly for a trivial url rename like this one.
  • Kapytanhook
    Kapytanhook over 8 years
    please add the explanation that it prefixes the length, I too was using it to output a textfile and didn't know the first 4 bytes where length.