我有一个Delphi 7应用程序,在那里我处理ANSI字符串,我需要计算它们的字符数(而不是字节数)。我总是知道与字符串相关联的字符集(以及代码页)。
因此,了解了字符集(代码页),我目前正在使用MultiByteToWideChar
来获取字符数。当字符集是中文、韩语或日语字符集之一,其中大多数字符的长度为2字节,并且简单地使用Length
函数不会得到我想要的东西时,这很有用。
但是,它仍然将复合字符计算为两个字符,我需要将它们计算为一个字符。现在,一些复合字符有Unicode的预编译版本,由于默认情况下使用MB_PRECOMPOSED
,这些字符将被正确地算作一个字符。但许多字符根本不作为预合成字符存在,例如希伯来语、阿拉伯语、泰语等中的字符,这些字符被算作两个。
所以真正的问题是:如何将复合字符算作单个字符我不介意将ANSI字符串转换为Wide字符串来计算字符数,无论如何,我已经在使用MultiByteToWideChar
了。
您可以像这样计算Unicode代码点:
function CodePointCount(P: PWideChar): Integer;
var
Count: Integer;
begin
Count := 0;
while Word(P^)<>0 do
begin
if (Word(P^)>=$D800) and (Word(P^)<=$DFFF) then
// part of surrogate pair
inc(Count)
else
inc(Count, 2);
inc(P);
end;
Result := Count div 2;
end;
这涵盖了你没有提到的问题。也就是说,UTF-16是可变宽度编码。
但是,这不会告诉您由UTF-16字符串表示的字形的数量。这是因为有些代码点表示组合字符。这些组合字符与其相邻字符组合形成一个等效字符。所以,多个代码点,单个字形。更多信息可在此处找到:http://en.wikipedia.org/wiki/Unicode_equivalence
这是一个更困难的问题。为了解决这个问题,您的代码需要充分理解每个Unicode代码点的含义。它是一个组合字符吗?它是如何结合的?您确实需要一个专用的Unicode库。例如重症监护室。
我给你的另一个建议是放弃使用ANSI代码页。如果你真的关心国际化,那么你需要使用Unicode。