我最好如何输出以下代码
#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
//
}
答案 0 :(得分:9)
没有API将CFString直接写入任何文件(包括stdout或stderr),因为您只能将字节写入文件。角色是(某种程度上)更理想的概念;它们太高,无法写入文件。这就像说“我想写这些像素”;你必须首先决定用它们写入的格式(比如PNG),然后用那种格式对它们进行编码,然后写出这些数据。
对于角色也是如此。您必须以某种格式将它们编码为字节,然后写入这些字节。
首先,您必须选择一种编码。要在终端上显示,您可能需要UTF-8,即kCFStringEncodingUTF8
。要写入文件......通常需要UTF-8。事实上,除非你特别需要别的东西,否则你几乎总是想要UTF-8。
接下来,您必须将字符编码为字节。创建C字符串是一种方法;另一种是创建CFData对象;还有一种是直接提取字节(非空终止)。
CFStringGetCString
function。CFStringGetBytes
function。你说你想坚持使用CF,所以我们将跳过C字符串选项(效率较低,因为无论调用write
都需要调用strlen
) - 它是更容易,但速度更慢,特别是当你在大字符串和/或频繁使用它时。相反,我们将创建CFData。
幸运的是,CFString提供了一个API,用于根据CFString的内容创建CFData对象。不幸的是,这仅适用于创建external representation。你可能不想写这个到stdout;它只适合写出常规文件的全部内容。
所以,我们需要自己降低一级和get bytes。此函数采用缓冲区(内存区域)和缓冲区的大小(以字节为单位)。
不要使用CFStringGetLength
作为缓冲区的大小。这会计算字符数,而不是字节数,字符数和字节数之间的关系并不总是线性的。 (例如,某些字符可以在单个字节中以UTF-8编码......但不是全部。几乎全部。而对于其他字符,所需的字节数会有所不同。)
正确的方法是两次调用CFStringGetBytes
:一次没有缓冲区(NULL
),因此它只会告诉你它会给你多少字节(不试图写入你没有给它的缓冲区);然后,您创建一个该大小的缓冲区,然后使用缓冲区再次调用它。
你可以使用malloc
创建一个缓冲区,但是你想坚持使用CF的东西,所以我们会这样做:create a CFMutableData object其容量是从第一个CFStringGetBytes
调用increase its length获得的字节数到相同的字节数,然后是get the data's mutable byte pointer。该指针是指向您需要写入的缓冲区的指针;它是您传递给CFStringGetBytes
的第二次调用的指针。
回顾到目前为止的步骤:
CFStringGetBytes
以找出缓冲区需要多大的数据。CFStringGetBytes
,这次使用缓冲区,将字符编码为数据对象中的字节。要将字节/数据写入纯CF文件,必须使用CFWriteStream。
可悲的是,没有CF等同于[NSFileHandle fileHandleWithStandardOutput]
这样的好的Cocoa API。创建stdout写入流的唯一方法是使用包含在URL中的stdout路径创建它。
您可以从路径中轻松创建URL;标准输出设备的路径为/dev/stdout
,因此创建URL如下所示:
CFURLRef stdoutURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR("/dev/stdout"), kCFURLPOSIXPathStyle, /*isDirectory*/ false);
(当然,就像你创建的所有东西一样,你需要释放它。)
拥有网址后,您可以create a write stream for the file so referenced。然后,您必须open the stream,然后write the data to it(您需要get the data's byte pointer和its length),最后close the stream。
请注意,如果您要写的内容不以换行符结尾,则可能缺少/不显示文本。 NSLog
代表您写入stderr时为您添加换行符;当你自己写信给stderr时,你必须这样做(或者承担后果)。
所以: