0

我想知道,有没有办法获取存储在 CoreFoundation 框架的 CFString 对象中的字符数(由底层 Unicode代码点表示)。

有可用的功能:CFStringGetLength,但它并没有做它看起来做的事情。

示例:我正在尝试获取包含位于第二个(SMP)Unicode 平面中的一个字符( Shavian Alphabet的字母“peep”)的字符串长度。

UInt8 arr[] = {0xf0, 0x90, 0x91, 0x90}; //UTF8
CFStringRef r = CFStringCreateWithBytes(0, arr, sizeof(arr),
                                        kCFStringEncodingUTF8, false);
CFIndex length = CFStringGetLength(r);

文档指出它返回:

存储在字符串中的字符数(根据 UTF-16 代码对)。

正如你所看到的,这句话是矛盾的——字符数并不总是等于 UTF-16 代码点的数量。但是,大括号中的部分更准确 - 函数的实际结果是 UTF-16 序列的数量。在我的示例中,函数的结果为2(以 UTF-16 编码字符所需的序列长度),而函数名称表明结果为1在我看来)。

我想找到一种方法来获取Unicode 代码点方面的字符数。有什么办法可以在 CoreFoundation 中做到这一点?

4

3 回答 3

1

我找到了解决方法。这并不完美,因为它可能需要额外转换为 UTF-32。

UInt8 arr[] = {0xf0, 0x90, 0x91, 0x90}; //UTF8, 
CFStringRef r = CFStringCreateWithBytes(0,
                                        arr,
                                        sizeof(arr),
                                        kCFStringEncodingUTF8,
                                        false);
CFIndex length = CFStringGetLength(r);
CFRange range = CFRangeMake(0, length);
CFIndex bytes;
CFStringGetBytes(r, range, kCFStringEncodingUTF32, 0, false, nullptr,
                 0, &bytes);
CFIndex characterCount = bytes/4;

变通方法利用了这样一个事实,即与 UTF-16 相比,UTF-32根据定义在单个实体中包含单个代码点。并且,由于实体被定义为四个字节大小,并且CFStringGetBytes能够获得转换后存储字符串所需的字节数,因此可以通过将字节数除以 4 来获得代码点数。

无论如何,CFStringGetBytes主要目的是执行实际转换,因此即使nullptr作为buffer参数传递,也有可能至少转换的主要部分实际发生。出于这个原因,很高兴听到该问题的另一种解决方案。

于 2013-03-23T01:16:22.403 回答
1

如果您想知道用户看到的“字符”的数量,无论规范化如何,请使用返回的范围遍历组合的字符序列CFStringGetRangeOfComposedCharactersAtIndex并计算迭代次数。

于 2014-12-15T11:52:14.827 回答
0

(这是我的猜测......)

我可以找到关于CFStringGetLength返回的“没有定义”。所有 Apple 手册都只是说UTF-16 代码对(?),老实说,我不明白它是什么意思。Unicode 很复杂,有许多微妙的不同概念。如果没有精确的术语,我们无法找出它是什么。

无论如何,在我的猜测中,它应该与[NSString length]as相同CFString并且NSString是免费桥接的,并且它们应该存储相同的数据以提供最佳性能。并[NSString length]返回UTF-16 Code Unit 的数量。这在 Apple 手册中有严格定义。请注意条款的不同。“代码单元”是定义明确的 Unicode 术语,但“代码对”是未知的。(有人知道吗?)“代码单元”也与“代码点”不同。

所以我认为它会返回“UTF-16 代码单元”,但我不会赌我的猜测。我会将其转换为NSString并调用[NSString length]以获取严格定义的数字。


要获得“Unicode Grapheme Clusters”,最好使用 Swift Strings。SwiftString具有访问 Grapheme Clusters 的本地接口。将它们转换为 SwiftString并对其进行迭代。

于 2020-02-11T11:38:12.393 回答