在Mac OS X中将CFSTR写入终端

时间:2013-09-09 14:27:01

标签: c macos core-foundation

我最好如何输出以下代码

#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
    //

}

1 个答案:

答案 0 :(得分:9)

没有API将CFString直接写入任何文件(包括stdout或stderr),因为您只能将字节写入文件。角色是(某种程度上)更理想的概念;它们太高,无法写入文件。这就像说“我想写这些像素”;你必须首先决定用它们写入的格式(比如PNG),然后用那种格式对它们进行编码,然后写出这些数据。

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

将字符编码为字节/数据

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

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

你说你想坚持使用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以找出缓冲区需要多大的数据。
  • 创建该容量的CFMutableData对象,并将其长度增加到该大小。
  • 获取CFMutableData对象的可变字节指针,这是您的缓冲区,并再次调用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 pointerits length),最后close the stream

请注意,如果您要写的内容不以换行符结尾,则可能缺少/不显示文本。 NSLog代表您写入stderr时为您添加换行符;当你自己写信给stderr时,你必须这样做(或者承担后果)。

所以: