我有一个字符串写入到TMemoryStream的方法,所以根据this embarcadero article,我应该将字符串的长度(以字符为单位)乘以Char类型的大小,以获取长度所需的长度(以字节为单位)以字节为单位)到WriteBuffer的参数.
以前:
rawHtml : string; //AnsiString ... memorystream1.WriteBuffer(Pointer(rawHtml)^,Length(rawHtml);
后:
rawHtml : string; //UnicodeString ... memorystream1.WriteBuffer(Pointer(rawHtml)^,Length(rawHtml)* SizeOf(Char));
我对Delphi的UnicodeString类型的理解是内部是UTF-16.但是我对Unicode的一般理解是,即使在2个字节中也不能表示所有的unicode字符,所以一些角色外部的字符将占用4个字节. Another of embarcadero’s articles似乎证实了我的怀疑,“其实呢,一个Char不等于两个字节!
所以…让我想知道长度(rawHtml)* SizeOf(Char)是否真的足够强大以保持一致的准确性,或者是否有更好的方法来确定字符串的大小会更准确?
解决方法
My understanding of Delphi’s UnicodeString type is that it’s UTF-16
internally.
您对于Delphi的UnicodeString的UTF-16编码是正确的.这意味着一个16位字符足够宽,可以将Basic Multilingual Plane中的所有code points作为字符串数组的一个Char元素.
But my general understanding of Unicode is that not all
unicode characters can be represented even in 2 bytes,that some
corner case foreign characters will take 4 bytes.
但是,这里有一点误解.长度函数不会对字符进行任何深度检查,只需返回16位WideChar元素的数量,而不考虑字符串中的任何代理.这意味着如果您将任何Supplementary Planes中的单个字符分配给UnicodeString,则长度将返回2.
program Egyptian; {$APPTYPE CONSOLE} var S: UnicodeString; begin S := #$1304E; // single char Writeln(Length(S)); Readln; end.
结论:字符串数据的字节大小始终是固定的,并且等于Length(S)* SizeOf(Char),无论S是否包含任何可变长度的字符.