16

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?

2 Answers 2

19

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.

Sign up to request clarification or add additional context in comments.

5 Comments

This worked for me after I removed the "self.WriteBuffer(len, 4);" - that was writing some gibberish characters to the output file.
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.
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.
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.
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.
19

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(); 

1 Comment

Note: this class have not methods to write an already encoded UTF8 string...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.