我们可以在 Sydney 的手机中安全地使用 ansiString 吗?

Can we safely use ansiString in mobile with Sydney?

当我阅读 Migrating Delphi Code to Mobile from Desktop 时,他们说要避免使用 AnsiString。有什么理由吗? AnsiString 使用的内存比 UnicodeString 少 2 倍,是 JSON 的完美容器。那么,我可以安全地使用 AnsiString,还是需要继续使用 UnicodeString(为什么)?

您可以在移动平台上使用 8 位字符串。但安全取决于您使用的是哪种 8 位字符串。

对于除 Windows 之外的任何内容,甚至在 Windows 上,使用 AnsiString 都是非常糟糕的主意。 AnsiString 是遗留类型,虽然它在 10.4 中在移动平台上重新启用,但这并不意味着您应该使用它,更不意味着您可以安全地使用它。

AnsiString 的一个问题是迟早会在您的代码中进行转换,因为整个 RTL 和 FMX 使用的默认字符串类型是 UTF-16 字符串类型,您可能会丢失原始数据。

可以在移动设备(和其他平台)上安全使用的字符串类型是stringUTF8StringRawByteString.

当谈到RawByteString时,它只能安全​​地用于代码页不可知的操作。查看更多:Delphi XE - RawByteString vs AnsiString

JSON 文件不支持 ANSI 编码,因此 Unicode 是您唯一的选择。 UTF-8 和 UTF8String 会做得更好,因为这也是任何 JSON 数据交换的默认编码。

就各种 AnsiXXX 函数而言,最好的选择是编写您自己的适用于 UTF-8 字符串的例程。您还可以使用适用于通用字符串类型的标准函数,但由于要转换为 UTF-16 并返回,它们速度较慢。


在移动设备 (Android) 上使用 AnsiString 时数据丢失的说明

Android 规范只要求实现几个标准字符集。这包括 ISO-8859-1

https://developer.android.com/reference/java/nio/charset/Charset

对于您依赖于特定设备的任何其他内容。

例如下面的例子 AnsiString 对于法语字符集工作正常,但对于克罗地亚语和中文字符集就失败了。

var
  s: string;
  u: UTF8String;
  a: AnsiString;
begin
  s := 'é à è ù â ê î ô û ç ë ï ü';
  a := s;
  u := s;
  Memo1.Lines.Add(s);
  Memo1.Lines.Add(u);
  Memo1.Lines.Add(a);

  s := 'š đ č ć ž Š Đ Č Ć Ž';
  a := s;
  u := s;
  Memo1.Lines.Add(s);
  Memo1.Lines.Add(u);
  Memo1.Lines.Add(a);

  s := '新年';
  u := s;
  a := s;
  Memo1.Lines.Add(s);
  Memo1.Lines.Add(u);
  Memo1.Lines.Add(a);
end;

Delphi 当您在可能发生数据丢失的位置之间进行不安全的类型转换时,编译器会发出警告,谨慎的做法是使用其他一些字符串类型来修复所有这些代码。

W1058 Implicit string cast with potential data loss from 'string' to 'AnsiString'

直接在 UTF-8 和 UTF-16 字符串类型之间转换时也会出现警告,但要清除这些警告,您可以显式转换为 stringUTF8String 类型,因为编译器将在后台进行适当的转换,所有信息将被保留(注意:Unicode 规范化可能在此过程中发生)。

W1057 Implicit string cast from 'string' to 'UTF8String'