引用Delphi XE8帮助:
对于单字节和多字节字符串,Length返回字符串使用的字节数.UTF-8的示例:
Run Code Online (Sandbox Code Playgroud)Writeln(Length(Utf8String('1¢'))); // displays 3对于Unicode(WideString)字符串,Length返回字节数除以2.
这引起了一些重要问题:
Length 将字符串视为数组时返回元素数.
Length则为您提供字节数,因为字节数与元素数相同.Length是字节数的一半,因为每个元素的宽度为2个字节.你的字符串'1¢'有两个代码点,但第二个代码点需要两个字节来用UTF-8编码.因此Length(Utf8String('1¢'))评估为三.
你SizeOf在问题标题中提到.传递一个字符串变量SizeOf将始终返回指针的大小,因为字符串变量在引擎盖下只是一个指针.
针对您的具体问题:
为什么处理上的差异根本就存在?
如果您认为Length与字节有关,则只有区别.但这是错误的思考方式,它Length始终返回一个元素计数,当以这种方式查看时,所有字符串类型的行为都是统一的,实际上所有数组类型都是如此.
为什么Length()没有做它预期的事情,只返回参数的长度(如,元素的数量),而不是在某些情况下给出字节大小?
它总是返回元素数.恰好是当元素大小是单个字节时,元素计数和字节计数恰好相同.实际上,您引用的文档也包含您提供的摘录上方的以下内容:返回字符串中的字符数或数组中的元素数.这是关键文本.您所包含的摘录旨在说明此斜体文本的含义.
为什么它声明它将结果除以2(Unicode(UTF-16)字符串?AFAIK UTF-16最多为4字节,因此会产生错误的结果.
UTF-16字符元素总是16位宽.但是,某些Unicode代码点需要两个字符元素进行编码.这些字符元素对称为代理对.
您希望,我希望Length能够返回字符串中的代码点数.但事实并非如此.它返回字符元素的数量.对于可变长度编码,代码点的数量不一定与字符元素的数量相同.如果您的字符串被编码为UTF-32,那么代码点的数量将与字符元素的数量相同,因为UTF-32是一个恒定大小的编码.
计算代码点的一种快速方法是扫描字符串检查代理对.当您遇到代理对时,请计算一个代码点.否则,当您遇到不属于代理项对的字符元素时,请计算一个代码点.在伪代码中:
N := 0;
for C in S do
if C.IsSurrogate then
inc(N)
else
inc(N, 2);
CodePointCount := N div 2;
Run Code Online (Sandbox Code Playgroud)
另一个要点是代码点数与可见字符数不同.一些代码点组合字符并与其相邻代码点组合以形成单个可见字符或字形.
最后,如果你希望做的就是找到字符串有效负载的字节大小,请使用以下表达式:
Length(S) * SizeOf(S[1])
Run Code Online (Sandbox Code Playgroud)
此表达式适用于所有类型的字符串.
对功能要非常小心System.SysUtils.ByteLength.从表面上看,这似乎就是你想要的.但是,该函数返回UTF-16编码字符串的字节长度.因此,如果你传递它AnsiString,比如说,那么返回的值ByteLength是该字节数的两倍AnsiString.
| 归档时间: |
|
| 查看次数: |
6132 次 |
| 最近记录: |