我正在移植一些德尔福7码XE4,所以,unicode是主题在这里。
我有其中一个字符串被写入到内存流的方法,所以根据这个Embarcadero的文章 ,我应该乘以字符串的长度(以字符)倍char类型的大小,以获得长度所需要的字节长度(以字节为单位)参数WriteBuffer。
所以之前:
rawHtml : string; //AnsiString
...
memorystream1.WriteBuffer(Pointer(rawHtml)^, Length(rawHtml);
后:
rawHtml : string; //UnicodeString
...
memorystream1.WriteBuffer(Pointer(rawHtml)^, Length(rawHtml)* SizeOf(Char));
我的德尔福的UnicodeString类型的理解是,这是UTF-16内部。 但是,我的Unicode的一般理解是,并不是所有的Unicode字符甚至可以在2个字节表示,一些极端情况外文字符将采取4个字节。 另一种英巴卡迪诺的文章似乎证实了我的怀疑,“事实上,它甚至不是总是成立一个字符等于两个字节!”
所以......这让我不知道是否Length(rawHtml)* SizeOf(Char)
是真的要强大到足以是始终如一的精确,或者是否有更好的方法来确定字符串,将更加准确的大小?
我的德尔福的UnicodeString类型的理解是,这是UTF-16内部。
您将德尔福的UTF-16编码正确UnicodeString
。 这意味着一个16位的字符是什么宽度不足以代表所有代码点从基本多文种平面为只有一个Char
元素string
数组。
但是,我的Unicode的一般理解是,并不是所有的Unicode字符甚至可以在2个字节表示,一些极端情况外文字符将采取4个字节。
但是,你有一点误解这里。 Length
函数不执行任何字符的深度检查,只是返回16位的数WideChar
元素,而没有考虑到你的字符串中的任何替代品。 这意味着,如果你从任意指定一个字符补充飞机到UnicodeString
, Length
将返回2。
program Egyptian;
{$APPTYPE CONSOLE}
var
S: UnicodeString;
begin
S := #$1304E; // single char
Writeln(Length(S));
Readln;
end.
结论 :字符串数据的字节大小始终是固定的,并且等于Length(S) * SizeOf(Char)
如果不管S
包含任何可变长度字符。
德尔福UnicodeString
编码与UTF-16。 UTF-16是可变长度编码,就像UTF-8。 换句话说,一个单一的统一代码点可能需要多个字符要素进行编码它。 作为关注点,唯一的固定长度Unicode编码是UTF-32。 的UTF-16编码使用16位字符的元素,因此而得名。
在一个Unicode Delphi中, Char
是一个别名WideChar
其是UTF-16字符元素。 并string
是一个别名UnicodeString
,这是阵列WideChar
元素。 的Length()
函数返回在数组中元素的数目。
因此, SizeOf(Char)
始终是2 UnicodeString
。 一些Unicode码点被编码有多个字符的元素,或Char
秒。 但Length()
返回的字符元素的数目,而不是代码点的数目。 汉字元素都具有相同的尺寸。 所以
memorystream1.WriteBuffer(Pointer(rawHtml)^, Length(rawHtml)* SizeOf(Char));
是正确的。
其他人解释的UnicodeString是如何编码以及如何计算它的字节长度。 我只是想提及的是,RTL已经有这样的功能- SysUtils.ByteLength()
memorystream1.WriteBuffer(PChar(rawHtml)^, ByteLength(rawHtml));
你在做什么是正确的(除了sizeof(字符))。
你指的是什么,不是一个性质是指一个代码点(例如由于代理对)。 串中,但USC2编码(NOT UTF-16)字符占用的字节的确切量随Length( Str ) * sizeof( Char )
需要注意的是在Delphi中使用的Unicode编码是一样的所有Windows API调用期望在....W¯¯变种。