我们可以在 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 字符串类型,您可能会丢失原始数据。
您可以在移动设备(和其他平台)上安全使用的字符串类型是string
、UTF8String
和 RawByteString
.
当谈到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 字符串类型之间转换时也会出现警告,但要清除这些警告,您可以显式转换为 string
或 UTF8String
类型,因为编译器将在后台进行适当的转换,所有信息将被保留(注意:Unicode 规范化可能在此过程中发生)。
W1057 Implicit string cast from 'string' to 'UTF8String'
当我阅读 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 字符串类型,您可能会丢失原始数据。
您可以在移动设备(和其他平台)上安全使用的字符串类型是string
、UTF8String
和 RawByteString
.
当谈到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 字符串类型之间转换时也会出现警告,但要清除这些警告,您可以显式转换为 string
或 UTF8String
类型,因为编译器将在后台进行适当的转换,所有信息将被保留(注意:Unicode 规范化可能在此过程中发生)。
W1057 Implicit string cast from 'string' to 'UTF8String'