1

How can I write a Unicode text file in Delphi?

Currently I simply use AssignFile, RewriteFile, and Writeln, but this does not write Unicode characters.

Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
Wolfgang Bures
  • 509
  • 4
  • 12
  • 1
    Why are you using 1980 file I/O in modern versions of Delphi? Use `TFileStream` instead. It's existed for more than 2 decades now. You're using file I/O that is from Turbo Pascal 1. Even using a `TStringList.SaveToFile` would be better when dealing with text files. – Ken White Nov 28 '20 at 22:01
  • 2
    Or even better, use [`TStreamWriter`](http://docwiki.embarcadero.com/Libraries/en/System.Classes.TStreamWriter) instead. – Remy Lebeau Nov 28 '20 at 22:16

2 Answers2

12

You shouldn't be using old Pascal I/O at all. That did its job back in the 80s but is very obsolete today.


This century, you can use the TStringList. This is very commonly used in Delphi. For instance, VCL controls use TStrings to access a memo's lines of text and a combo box's or list box's items.

var SL := TStringList.Create;
try
  SL.Add('∫cos(x)dx = sin(x) + C');
  SL.Add('¬(a ∧ b) ⇔ ¬a ∨ ¬b');
  SL.SaveToFile(FileName, TEncoding.UTF8);
finally
  SL.Free;
end;

Fore more advanced needs, you can use a TStreamWriter:

var SW := TStreamWriter.Create(FileName, False, TEncoding.UTF8);
try
  SW.WriteLine('αβγδε');
  SW.WriteLine('ωφψξη');
finally
  SW.Free;
end;

And for very simple needs, there are the new TFile methods in IOUtils.pas:

var S := '⌬ is aromatic.';
TFile.WriteAllText(FileName, S, TEncoding.UTF8);         // string (possibly with linebreaks)

var Lines: TArray<string>;
Lines := ['☃ is cold.', '☼ is hot.'];
TFile.WriteAllLines(FileName, Lines, TEncoding.UTF8);    // string array

As you can see, all these modern options allow you to specify UTF8 as encoding. If you prefer to use some other encoding, like UTF16, that's fine too.


Just forget about AssignFile, Reset, Rewrite, Append, CloseFile etc.

Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
5

Other users have given you options but nobody has answered (I guess). You can´t write UTF8 using Writeln because at runtime, any string is switched back to Ansi. All the proposal seems very good ones however.

Try this short program

program utf8;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

var s : string; u : AnsiString;   some : Text;

begin
  try
    { TODO -oUser -cConsole Main : Insert code here }
    Assign(some,'data.txt');
    rewrite(some);
    s := 'física';
    u := UTF8Encode (s);
    writeln(some,s);
    writeln(some,u);
    Close(some);
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

Enable "use debug dcu" and carefully follow the Writeln execution. You will learn that despite the fact of being UTF8 encoded, u is switched back to Ansi at some point.

Edition: I was wrong. You can indeed with:

Assign(FileName,CP_UTF8);

Check help for System.Assign

alvaroc
  • 433
  • 5
  • 14