Delphi Unicode字符串长度,以字节为单位

时间:2013-05-13 19:50:12

标签: delphi unicode delphi-xe4

我正在努力将一些Delphi 7代码移植到XE4,因此,unicode就是这里的主题。

我有一个方法,其中字符串被写入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等于两个字节并不总是正确的!”

所以...让我想知道Length(rawHtml)* SizeOf(Char)是否真的足够强大以保持一致,或者是否有更好的方法来确定更准确的字符串大小?

4 个答案:

答案 0 :(得分:10)

Delphi的UnicodeString使用UTF-16编码。 UTF-16是一种可变长度编码,就像UTF-8一样。换句话说,单个Unicode代码点可能需要多个字符元素来对其进行编码。作为一个兴趣点,唯一的固定长度Unicode编码是UTF-32。 UTF-16编码使用16位字符元素,因此名称为。

在Unicode Delphi中,CharWideChar的别名,它是UTF-16字符元素。 stringUnicodeString的别名,是WideChar元素的数组。 Length()函数返回数组中元素的数量。

因此,SizeOf(Char)始终为UnicodeString。某些Unicode代码点使用多个字符元素或Char进行编码。但是Length()会返回字符元素的数量,不会返回代码点的数量。字符元素都具有相同的大小。所以

memorystream1.WriteBuffer(Pointer(rawHtml)^, Length(rawHtml)* SizeOf(Char));

是对的。

答案 1 :(得分:7)

  

我对Delphi的UnicodeString类型的理解是它是UTF-16   内部。

你对Delphi的UnicodeString的UTF-16编码是正确的。这意味着一个16位字符的宽度足以表示code points中的所有Basic Multilingual PlaneChar数组的string个元素完全相同。

  

但我对Unicode的一般理解并非全部   unicode字符甚至可以表示为2个字节,即一些   角落外壳字符将占用4个字节。

但是,你在这里有一点误解。 Length函数不会对字符执行任何深入检查,只返回16位WideChar元素的数量,而不考虑字符串中的任何代理项。这意味着如果您将Supplementary Planes中的任何一个字符分配给UnicodeStringLength将返回2.

program Egyptian;

{$APPTYPE CONSOLE}

var
  S: UnicodeString;

begin
  S := #$1304E;  // single char
  Writeln(Length(S));
  Readln;
end.

结论:字符串数据的字节大小始终是固定的,等于Length(S) * SizeOf(Char),无论S是否包含任何可变长度的字符。

答案 2 :(得分:4)

其他人已经解释了如何编码UnicodeString以及如何计算其字节长度。我只想提一下RTL已经有了这样的功能 - SysUtils.ByteLength()

memorystream1.WriteBuffer(PChar(rawHtml)^, ByteLength(rawHtml));

答案 3 :(得分:3)

你正在做的是正确的(使用sizeof(Char))。

您所指的是,不是一个字符指的是一个代码点(例如,由于代理对)。但是字符串中的USC2编码(非UTF-16)字符恰好占用了Length( Str ) * sizeof( Char )的字节数。

请注意,Delphi中使用的Unicode编码与.... W变体中的所有Windows API调用相同。