1

我将如何最好地输出以下代码

#include <CoreFoundation/CoreFoundation.h> // Needed for CFSTR
int main(int argc, char *argv[])
{
    char *c_string = "Hello I am a C String. :-).";
    CFStringRef cf_string = CFStringCreateWithCString(0, c_string, kCFStringEncodingUTF8);

    // output cf_string
    //

}
4

1 回答 1

9

没有 API 可以将 CFString 直接写入任何文件(包括 stdout 或 stderr),因为您只能将字节写入文件。字符是一个(有点)更理想的概念;它们太高级而无法写入文件。这就像说“我想写这些像素”;您必须首先决定将它们写入的格式(例如 PNG),然后以该格式对其进行编码,然后写入该数据。

对字符也是如此。您必须将它们编码为某种格式的字节,然后写入这些字节。

将字符编码为字节/数据

首先,您必须选择一种编码。要在终端上显示,您可能需要 UTF-8,即kCFStringEncodingUTF8. 对于写入文件……您通常需要 UTF-8。事实上,除非您特别需要其他东西,否则您几乎总是需要 UTF-8。

接下来,您必须将字符编码为字节。创建 C 字符串是一种方法;另一种是创建一个CFData对象;还有一个是直接提取字节(非空终止)。

你说你想坚持使用 CF,所以我们将跳过 C 字符串选项(无论如何效率较低,因为任何调用write都必须调用strlen)——它更容易,但速度更慢,特别是当你在大字符串上使用它时和/或经常。相反,我们将创建 CFData。

幸运的是,CFString 提供了一个 API 来从 CFString 的内容创建一个 CFData 对象。不幸的是,这只适用于创建外部表示。您可能不想将其写入标准输出;它只适合写为常规文件的全部内容。

所以,我们需要下拉一个级别并自己获取字节。此函数采用缓冲区(内存区域)和该缓冲区的大小(以字节为单位)。

不要用于CFStringGetLength缓冲区的大小。这计算字符数,而不是字节数,并且字符数和字节数之间的关系并不总是线性的。(例如,某些字符可以在单个字节中以 UTF-8 编码……但不是全部。不是几乎全部。对于其他字符,所需的字节数各不相同。)

正确的方法是调用CFStringGetBytes 两次:一次没有缓冲区(NULL),然后它会简单地告诉你它会给你多少字节(而不是试图写入你没有给它的缓冲区);然后,您创建一个该大小的缓冲区,然后使用该缓冲区再次调用它。

可以使用 创建一个缓冲区malloc,但您想坚持使用 CF 的东西,所以我们将这样做:创建一个 CFMutableData 对象,其容量是您从第一次CFStringGetBytes调用中获得的字节数,将其长度增加到相同字节数,然后获取数据的可变字节指针。该指针是指向您需要写入的缓冲区的指针;它是您传递给第二次调用的指针CFStringGetBytes

回顾一下到目前为止的步骤:

  • 在没有缓冲区CFStringGetBytes的情况下调用以了解缓冲区需要多大。
  • 创建该容量的 CFMutableData 对象并将其长度增加到该大小。
  • 获取 CFMutableData 对象的可变字节指针,即您的缓冲区,并CFStringGetBytes再次调用,这次使用缓冲区,将字符编码为数据对象中的字节。

写出来

要将字节/数据写入纯 CF 中的文件,您必须使用CFWriteStream

可悲的是,没有 CF 等价于漂亮的 Cocoa API,例如[NSFileHandle fileHandleWithStandardOutput]. 创建到 stdout 的写入流的唯一方法是使用包含在 URL 中的 stdout 路径来创建它。

您可以从路径轻松创建 URL;标准输出设备的路径是/dev/stdout,因此创建 URL 如下所示:

CFURLRef stdoutURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR("/dev/stdout"), kCFURLPOSIXPathStyle, /*isDirectory*/ false);

(当然,就像您创建的所有内容一样,您需要发布它。)

有了 URL,您就可以为所引用的文件创建一个写入流。然后,您必须打开流,然后您可以将数据写入其中(您需要获取数据的字节指针及其长度),最后关闭流

请注意,如果您写出的内容不以换行符结尾,您可能会丢失/未显示文本。NSLog当它代表您写入 stderr 时为您添加一个换行符;当您自己写信给 stderr 时,您必须这样做(或承担后果)。

所以:

于 2013-09-10T19:13:13.233 回答