gpt4 book ai didi

iphone - NSString 的 UTF8String 的 CFString Equiv 是什么?

转载 作者:太空狗 更新时间:2023-10-30 03:46:28 25 4
gpt4 key购买 nike

我今天陷入了愚蠢的困境,因为我无法将一段简单的 ObjC 代码转换为其 Cpp 等效代码。我有这个:

  const UInt8 *myBuffer = [(NSString*)aRequest UTF8String];

我试图用这个替换它:
  const UInt8 *myBuffer = (const UInt8 *)CFStringGetCStringPtr(aRequest, kCFStringEncodingUTF8);

这一切都在一个严密的单元测试中,它使用 CFNetwork API 通过套接字编写示例 HTTP 请求。我有正在尝试移植到 C++ 的工作 ObjC 代码。我正在逐渐用他们的免费桥接等价物替换 NS API 调用。到目前为止,一切都是一对一的,直到最后一行。这就像需要完成的最后一块。

最佳答案

这是 Cocoa 在幕后完成所有杂乱工作的事情之一,在您不得不卷起袖子自己动手之前,您永远不会真正意识到事情的复杂性。

为什么它不“简单”的简单答案是因为 NSString (和 CFString )处理处理多个字符集、Unicode 等的所有复杂细节,同时提供用于操作字符串的简单、统一的 API。它是最好的面向对象-“如何”的细节(NS|CF)String处理具有不同字符串编码(UTF8、MacRoman、UTF16、ISO 2022 日语等)的字符串是一个私有(private)实现细节。这一切都“有效”。

它有助于了解如何[@"..." UTF8String]作品。这是一个私有(private)的实现细节,所以这不是福音,而是基于观察到的行为。当你发送一个字符串 UTF8String消息,字符串做一些近似的事情(没有实际测试,所以把它当作伪代码,实际上有更简单的方法来做完全相同的事情,所以这过于冗长):

- (const char *)UTF8String
{
NSUInteger utf8Length = [self lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
NSMutableData *utf8Data = [NSMutableData dataWithLength:utf8Length + 1UL];
char *utf8Bytes = [utf8Data mutableBytes];
[self getBytes:utf8Bytes
maxLength:utf8Length
usedLength:NULL
encoding:NSUTF8StringEncoding
options:0UL
range:NSMakeRange(0UL, [self length])
remainingRange:NULL];
return(utf8Bytes);
}

您不必担心处理缓冲区的内存管理问题 -UTF8String返回是因为 NSMutableData是自动发布的。

字符串对象可以自由地以它想要的任何形式保存字符串的内容,因此不能保证其内部表示是最适合您需要的表示(在本例中为 UTF8)。如果您只使用普通的 C,您将不得不管理一些内存以保存可能需要的任何字符串转换。曾经的简单 -UTF8String方法调用现在要复杂得多。

大部分 NSString实际上是在/与 CoreFoundation/ CFString 中实现的,所以显然有一条来自 CFStringRef 的路径-> -UTF8String .它只是不像 NSString 那样整洁和简单的 -UTF8String .大多数复杂情况与内存管理有关。以下是我过去处理它的方法:
void someFunction(void) {
CFStringRef cfString; // Assumes 'cfString' points to a (NS|CF)String.

const char *useUTF8StringPtr = NULL;
UInt8 *freeUTF8StringPtr = NULL;

CFIndex stringLength = CFStringGetLength(cfString), usedBytes = 0L;

if((useUTF8StringPtr = CFStringGetCStringPtr(cfString, kCFStringEncodingUTF8)) == NULL) {
if((freeUTF8StringPtr = malloc(stringLength + 1L)) != NULL) {
CFStringGetBytes(cfString, CFRangeMake(0L, stringLength), kCFStringEncodingUTF8, '?', false, freeUTF8StringPtr, stringLength, &usedBytes);
freeUTF8StringPtr[usedBytes] = 0;
useUTF8StringPtr = (const char *)freeUTF8StringPtr;
}
}

long utf8Length = (long)((freeUTF8StringPtr != NULL) ? usedBytes : stringLength);

if(useUTF8StringPtr != NULL) {
// useUTF8StringPtr points to a NULL terminated UTF8 encoded string.
// utf8Length contains the length of the UTF8 string.

// ... do something with useUTF8StringPtr ...
}

if(freeUTF8StringPtr != NULL) { free(freeUTF8StringPtr); freeUTF8StringPtr = NULL; }
}

注意 : 我还没有测试过这段代码,但它是从工作代码修改而来的。所以,除了明显的错误,我相信它应该有效。

以上尝试获取指向缓​​冲区的指针 CFString用于存储字符串的内容。如 CFString如果字符串内容以 UTF8(或适当兼容的编码,例如 ASCII)编码,则很可能是 CFStringGetCStringPtr()将返回非 NULL .这显然是最好、最快的情况。如果由于某种原因无法获得该指针,请说 if CFString将其内容编码为 UTF16,然后分配一个缓冲区为 malloc()当它被转码为 UTF8 时,它足够大以包含整个字符串。然后,在函数结束时,它会检查是否分配了内存和 free()有必要的话。

现在了解一些提示和技巧... CFString “倾向于”(这是一个私有(private)实现细节,因此它可以并且确实会在不同版本之间发生变化)将“简单”字符串编码为 MacRoman,这是一种 8 位宽编码。 MacRoman 与 UTF8 一样,是 ASCII 的超集,因此所有 < 128 的字符都等同于它们的 ASCII 对应字符(或者,换句话说,任何 < 128 的字符都是 ASCII)。在 MacRoman 中,>= 128 的字符是“特殊”字符。它们都有 Unicode 等价物,并且往往是额外的货币符号和“扩展的西方”字符之类的东西。见 Wikipedia - MacRoman了解更多信息。但仅仅因为一个 CFString说它是 MacRoman( CFString kCFStringEncodingMacRoman 的编码值, NSString NSMacOSRomanStringEncoding 的编码值)并不意味着它有字符 >= 128 。如果 kCFStringEncodingMacRoman CFStringGetCStringPtr() 返回的编码字符串完全由 < 128 个字符组成,那么它完全等同于其 ASCII ( kCFStringEncodingASCII ) 编码表示,也完全等同于字符串 UTF8 ( kCFStringEncodingUTF8 ) 编码表示。

根据您的要求,您可以使用 kCFStringEncodingMacRoman 来“过关”。而不是 kCFStringEncodingUTF8打电话时 CFStringGetCStringPtr() .如果您的字符串需要严格的 UTF8 编码,但使用 kCFStringEncodingMacRoman,事情“可能”(可能)会更快,然后检查以确保 CFStringGetCStringPtr(string, kCFStringEncodingMacRoman) 返回的字符串只包含 < 128 的字符。如果字符串中有 >= 128 的字符,则通过 malloc() 走慢速路线一个缓冲区来保存转换后的结果。例子:
CFIndex stringLength = CFStringGetLength(cfString), usedBytes = 0L;

useUTF8StringPtr = CFStringGetCStringPtr(cfString, kCFStringEncodingUTF8);

for(CFIndex idx = 0L; (useUTF8String != NULL) && (useUTF8String[idx] != 0); idx++) {
if(useUTF8String[idx] >= 128) { useUTF8String = NULL; }
}

if((useUTF8String == NULL) && ((freeUTF8StringPtr = malloc(stringLength + 1L)) != NULL)) {
CFStringGetBytes(cfString, CFRangeMake(0L, stringLength), kCFStringEncodingUTF8, '?', false, freeUTF8StringPtr, stringLength, &usedBytes);
freeUTF8StringPtr[usedBytes] = 0;
useUTF8StringPtr = (const char *)freeUTF8StringPtr;
}

就像我说的,你不会真正体会到 Cocoa 自动为你做了多少工作,直到你必须自己做这一切。 :)

关于iphone - NSString 的 UTF8String 的 CFString Equiv 是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1609565/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com