从 XE2 开始,AssignFile()
有一个可选CodePage
参数设置输出文件的代码页:
function AssignFile(var F: File; FileName: String; [CodePage: Word]): Integer; overload;
Write()
并且Writeln()
两者都有支持UnicodeString
和WideChar
输入的重载。
因此,您可以创建一个将其代码页设置为 的文件,CP_UTF8
然后Write/ln()
在将 Unicode 字符串写入文件时自动将其转换为 UTF-8。
缺点是您将无法再使用AnsiChar
值写入 UTF-8 BOM,因为单个字节将被转换为 UTF-8,因此无法正确写入。您可以通过将 BOM 编写为单个 Unicode 字符(它实际上是 - U+FEFF
)而不是单个字节来解决此问题。
这适用于 XE2:
procedure TForm1.Button1Click(Sender: TObject);
var
Outfile: TextFile;
begin
AssignFile(Outfile, 'test_chinese.txt', CP_UTF8);
Rewrite(Outfile);
//This is the UTF-8 BOM
Write(Outfile, #$FEFF);
Writeln(Outfile, '总结');
Writeln(Outfile, '°C');
CloseFile(Outfile);
end;
话虽如此,如果您想要 D2009 和 XE2 之间更兼容和更可靠的东西,请TStreamWriter
改用:
procedure TForm1.Button1Click(Sender: TObject);
var
Outfile: TStreamWriter;
begin
Outfile := TStreamWriter.Create('test_chinese.txt', False, TEncoding.UTF8);
try
Outfile.WriteLine('总结');
Outfile.WriteLine('°C');
finally
Outfile.Free;
end;
end;
或者手动执行文件 I/O:
procedure TForm1.Button1Click(Sender: TObject);
var
Outfile: TFileStream;
BOM: TBytes;
procedure WriteBytes(const B: TBytes);
begin
if B <> '' then Outfile.WriteBuffer(B[0], Length(B));
end;
procedure WriteStr(const S: UTF8String);
begin
if S <> '' then Outfile.WriteBuffer(S[1], Length(S));
end;
procedure WriteLine(const S: UTF8String);
begin
WriteStr(S);
WriteStr(sLineBreak);
end;
begin
Outfile := TFileStream.Create('test_chinese.txt', fmCreate);
try
WriteBytes(TEncoding.UTF8.GetPreamble);
WriteLine('总结');
WriteLine('°C');
finally
Outfile.Free;
end;
end;