【问题标题】:Length of a UTF8String in DelphiDelphi中UTF8String的长度
【发布时间】:2021-03-10 12:25:43
【问题描述】:

无论保存字符串需要多少字节,我如何获取 UTF8String 中可见字符的数量?

【问题讨论】:

  • 这是一个复杂的话题。 Delphi 本身不提供任何东西来计算视觉长度,所以你必须自己做,或者更好地使用 Unicode 库,比如 ICU。计算 UTF-8 字符串中的 Unicode 代码点相当容易,但并不是那么简单,因为可能需要多个代码点才能产生 1 个可见的“字符”(字素簇),因此您必须考虑组合代码点等事情(口音、表情符号等)、无宽度代码点、双向修饰符等。这些东西本身不会在视觉上自行输出,但会影响可见输出。
  • MANAGING UTF-8 STRINGS 在第 15+16 页。
  • @JosefZ 这些页面没有解决 OP 的要求。 LengthUTF8String 是编码的 UTF 代码单元的数量,而不是 Unicode 代码点的数量,或者代码点产生的视觉字素的数量。
  • 如果UUTF8String,那么Length(string(U)) 通常是“可见字符”的实际数量可接受的近似值。在许多应用中,这个数字是完全正确的。但正如雷米指出的那样,也有不少例外。 (即使对于普通的stringLength(s) 也只是“可见字符”数量的近似值。)
  • 您可以将 UTF8String 转换为 UnicodeString 并使用 CharNextW(如果您在 Windows 下)来计算字符数:stackoverflow.com/a/32020629

标签: string delphi unicode


【解决方案1】:

如果你在 Windows 下,试试CharNextW:

uses
  Winapi.Windows,
  System.SysUtils;

function GetCharsCount(const AStr: UTF8String): Integer;
var
  P: PWideChar;
begin
  Result := 0;
  P := PWideChar(UnicodeString(AStr));
  while P <> '' do begin
    Inc(Result);
    P := CharNextW(P);
  end;
end;

【讨论】:

  • 可能值得指出的是,这种方法也可以用于普通的strings,而不仅仅是UTF8Strings(实际上,这段代码是从后者转换为前者开始的)。
  • @DavidHeffernan 实际上是这样的:“此函数在处理变音符号时使用默认的“用户”期望字符。例如:包含 U+0061 U+030a 的字符串“LATIN小写字母 A" + 上面的组合环" — 看起来像 "å",将推进两个代码点,而不是一个。包含 U+0061 U+0301 U+0302 U+0303 U+0304 的字符串 - 看起来像“a´^~¯”,将推进五个代码点,而不是一个,等等。“但是,P &lt;&gt; ''确实需要改成P^ &lt;&gt; #0,至少
  • 我认为这相当接近。以∫àéôx̅ȧa̎​b? 为例。可以说有 9 个可见字符。 Length(S) 返回 17,而 GetCharsCount 返回 10。你多久使用一次 U+200B:零宽度空间? (或者你有其他反例吗,@DavidHeffernan?)此外,由于 OP 正在谈论 UTF8String 而不是非常精确地定义“可见字符”,也许 OP 甚至会认为 Length(string(U)) 足够好他/她的需求?
  • 有趣的是,GetCharsCount 未能将 leading 代理对视为单个字符:b?(没有空格)据说是 2 个字符,但 @987654336 @ 据说是 3 个字符。是不是有点奇怪?
  • 抱歉,评论已删除。我的错。答案将受益于所有这一切的解释。或者也许只是欺骗了雷米的链接答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-11
  • 1970-01-01
相关资源
最近更新 更多