delphi - TFile.ReadAllText 与 TEncoding.UTF8 省略前 3 个字符

标签 delphi utf-8 text-files delphi-xe2

我有一个以此行开头的 UTF-8 文本文件:

<HEAD><META name=GENERATOR content="MSHTML 10.00.9200.16521"><body>

当我使用 TFile.ReadAllText 和 TEncoding.UTF8 读取此文件时:

MyStr := TFile.ReadAllText(ThisFileNamePath, TEncoding.UTF8);

然后文本文件的前 3 个字符被省略,因此 MyStr 结果为:

'AD><META name=GENERATOR content="MSHTML 10.00.9200.16521"><body>...'

但是,当我使用 TFile.ReadAllText 读取此文件而不使用 TEncoding.UTF8 时:

MyStr := TFile.ReadAllText(ThisFileNamePath);

然后文件被完整且正确地读取:

<HEAD><META name=GENERATOR content="MSHTML 10.00.9200.16521"><body>...

TFile.ReadAllText 有错误吗?

最佳答案

前三个字节被跳过,因为 RTL 代码假定文件包含 UTF-8 BOM。显然你的文件没有。

TUTF8Encoding 类实现指定 UTF-8 BOM 的 GetPreamble 方法。 ReadAllBytes 会跳过您传递的编码指定的前导码。

一个简单的解决方案是将文件读入字节数组,然后使用 TEncoding.UTF8.GetString 将其解码为字符串。

var
  Bytes: TBytes;
  Str: string;
....
Bytes := TFile.ReadAllBytes(FileName);
Str := TEncoding.UTF8.GetString(Bytes);

更全面的替代方案是创建一个忽略 UTF-8 BOM 的 TEncoding 实例。

type
  TUTF8EncodingWithoutBOM = class(TUTF8Encoding)
  public
    function Clone: TEncoding; override;
    function GetPreamble: TBytes; override;
  end;

function TUTF8EncodingWithoutBOM.Clone: TEncoding;
begin
  Result := TUTF8EncodingWithoutBOM.Create;
end;

function TUTF8EncodingWithoutBOM.GetPreamble: TBytes;
begin
  Result := nil;
end;

实例化其中一个(每个进程只需要一个实例)并将其传递给 TFile.ReadAllText

使用 TUTF8EncodingWithoutBOM 的单例实例的优点是您可以在需要 TEncoding 的任何地方使用它。

关于delphi - TFile.ReadAllText 与 TEncoding.UTF8 省略前 3 个字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17133430/

相关文章:

ios - 在 iOS 中访问文本文件内容和字符数非常慢

delphi - 删除已发布的空部分总是安全吗?

delphi - 如果调用 FastReport.PrepareReport,则 ISAPI Web 应用程序挂起

java - 输入字符串已编码,需要原始字符串 - Java 代码

python - 为什么 Python 不能正确显示此文本? (UTF-8解码问题)

datetime - 将 12 小时日期/时间转换为 24 小时日期/时间

android - string.xml 文件中的字符串大小和字体更改

德尔福ADO : necessary to clean up parameters?

windows - 截取使用 createdesktop api 创建的桌面的屏幕截图

http - 使用 http4 将任何网页内容转换为 UTF-8