此单元测试在Delphi模式下使用Free Pascal 3.0成功运行:
procedure TFreePascalTests.TestUTF8Decode;
var
Raw: RawByteString;
Actual: string;
begin
Raw := UTF8Encode('关于汉语');
Actual := string( UTF8Decode(Raw) ); // <--- cast from UnicodeString
CheckEquals('关于汉语', Actual);
// check Windows ANSI code page
CheckEquals(1252, GetACP);
// check Free Pascal value (determines how CP_ACP is interpreted)
CheckEquals(65001, DefaultSystemCodePage);
end;
UTF8Decode返回UnicodeString。如果没有硬类型转换为字符串,编译器会警告不安全的转换:
警告:隐式字符串类型转换,可能会丢失数据 &#34;的UnicodeString&#34;到&#34; AnsiString&#34;
(使用Lazarus 1.6 / FPCUnit GUITestrunner测试)
根据http://wiki.freepascal.org/Character_and_string_types#String,字符串类型默认为AnsiString(如果{$ H +}开关设置为使用AnsiString而不是ShortString)。
看起来Free Pascal将Unicode字符串存储在AnsiString变量中。 (即使没有演员表,测试成功)
问题:由于测试成功,我可以假设使用强制转换(抑制警告)是安全的,而不会有数据丢失的风险吗?
答案 0 :(得分:3)
一般来说,强制转换是不安全的,因为您仍在将UnicodeString转换为AnsiString,并且在编译时不知道AnsiString的编码。当您明确地执行此操作时,警告才会消失,编译器会假定您知道自己在做什么。
如果转换依赖于系统上的编码设置:它是UTF-8,那么Actual
包含UTF-8编码的字符串,它可以正常工作,或者系统上的特定区域设置支持你的字符正在使用。如果您在具有e的系统上运行此代码。 G。 CP1250,它会失败。管理变量是DefaultSystemCodePage
。在启动时,它由FPC RTL使用系统的编码进行初始化。但是,有一些框架(如LCL)会覆盖它并将其设置为e。 G。 UTF-8。
除了{$modeswitch unicodestrings}
和{$mode delphi}
等于string
之外,请使用unicodestring
,因此编码将与区域设置无关。