2008-08-15 88 views
16

我正在寻找相当于Windows的_wfopen()在Mac OS X下的任何想法?_wfopen在Mac OS X下相当于

我需要这个以便移植一个使用wchar*作为它的File接口的Windows库。由于这是一个跨平台的库,我无法依赖客户端应用程序如何获取文件路径并将其提供给库。

回答

14

Mac OS X中的POSIX API可与UTF-8字符串一起使用。为了将wchar_t字符串转换为UTF-8,可以使用Mac OS X中的CoreFoundation框架。

这里是一个类,它将包装一个来自wchar_t字符串的UTF-8生成的字符串。

class Utf8 
{ 
public: 
    Utf8(const wchar_t* wsz): m_utf8(NULL) 
    { 
     // OS X uses 32-bit wchar 
     const int bytes = wcslen(wsz) * sizeof(wchar_t); 
     // comp_bLittleEndian is in the lib I use in order to detect PowerPC/Intel 
     CFStringEncoding encoding = comp_bLittleEndian ? kCFStringEncodingUTF32LE 
                 : kCFStringEncodingUTF32BE; 
     CFStringRef str = CFStringCreateWithBytesNoCopy(NULL, 
                 (const UInt8*)wsz, bytes, 
                 encoding, false, 
                 kCFAllocatorNull 
                 ); 

     const int bytesUtf8 = CFStringGetMaximumSizeOfFileSystemRepresentation(str); 
     m_utf8 = new char[bytesUtf8]; 
     CFStringGetFileSystemRepresentation(str, m_utf8, bytesUtf8); 
     CFRelease(str); 
    } 

    ~Utf8() 
    { 
     if(m_utf8) 
     { 
      delete[] m_utf8; 
     } 
    } 

public: 
    operator const char*() const { return m_utf8; } 

private: 
    char* m_utf8; 
}; 

用法:

const wchar_t wsz = L"Here is some Unicode content: éà€œæ"; 
const Utf8 utf8 = wsz; 
FILE* file = fopen(utf8, "r"); 

这将用于读取或写入文件。

0

如果您使用可可,使用NSString相当简单。只需使用-initWithBytes:length:encoding :(或者可能是-initWithCString:encoding :)加载UTF16数据,然后通过调用UTF8String得到UTF8版本的结果。然后,使用新的UTF8字符串作为参数调用fopen。

不管语言如何,你都可以使用UTF-8字符串明确调用fopen--尽管如此,不能用OSX上的C++来帮助 - 对不起。

+0

我不使用Cocoa,而是使用C++,而不是Objective-C。如果你正确地将UTF-8字符串转换为fopen(),我可以将UTF-16字符串转换为UTF-8,但是在Mac OS X(再次使用C/C++)时这很容易实现。 – 2008-09-17 09:20:11

+0

由于我依赖于CFString而不是NSString,但它的基本思想是相同的,因此不是明确的答案。谢谢。 – 2009-01-21 17:37:14

4

你只是想打开一个文件句柄使用可能包含Unicode字符的路径,对吧?只需通过文件系统表示fopen的路径即可。

  • 如果路径从股市Mac OS X的框架来(例如,开放式面板是否碳或可可),你不会需要做任何转换,并能够使用它作为-is。

  • 如果您自己生成部分路径,您应该从路径创建一个CFStringRef,然后通过文件系统表示将其传递给POSIX API,如openfopen

一般来说,你不必为大多数应用程序做很多事情。例如,许多应用程序可能会将辅助数据文件存储在用户的应用程序支持目录中,但只要这些文件的名称是ASCII,并且您使用标准的Mac OS X API来查找用户的应用程序支持目录,则不需要对这两个组件构建的路径进行一堆偏执变换。

编辑补充:我会使用类似wcstombs强烈警告针对任意转换一切为UTF-8,因为文件系统编码不一定是相同于所生成的UTF-8。 Mac OS X和Windows都对文件系统路径中使用的编码使用了特定(但不同)的规范分解规则。

例如,他们需要决定是否将“é”存储为一个或两个代码单元(LATIN SMALL LETTER E WITH ACUTELATIN SMALL LETTER E,然后是COMBINING ACUTE ACCENT)。这些将导致两种不同的和不同长度的字节序列,并且Mac OS X和Windows都可以避免在同一个目录中将多个具有相同名称的文件(如用户感知它们)一样。

有关如何执行此规范化分解的规则可能变得非常多毛,所以不要试图自己实现它,最好将它留给系统框架为您执行繁重工作的功能。

2

@JKP:

不能在MacOS X的所有函数接受UTF8,但文件名和文件路径可能是UTF8,从而处理文件访问(打开,FOPEN,统计等),所有POSIX函数接受UTF8。

请参阅here。报价:

文件名称如何查看API级别 取决于API。当前碳 API以 UTF-16字符的数组处理文件名; POSIX的处理 他们作为UTF-8的数组,这是为什么UTF-8在终端工作良好的 。它如何存储在磁盘上取决于 磁盘格式; HFS +使用UTF-16,但是 在大多数情况下并不重要。

其他一些POSIX函数也处理UTF8。例如。处理用户名,组名或用户密码的函数使用UTF8来存储信息(因此用户名可以是日文,密码可以是中文,没问题)。

但并非所有处理UTF8。例如。对于所有字符串函数,UTF8字符串只是普通的C字符串,而高于126的字符没有特殊含义。他们不理解构成单个Unicode字符的多个字节(C中的字符)的概念。其他API如何处理传递给它们的char *指针是不同于API到API的。但是,通常您可以这么说:

该函数只接受纯ASCII字符的C字符串(仅在0到126之间)或接受UTF8。通常函数不允许超过126的字符,并且以UTF8以外的任何其他编码解释它们。如果情况确实如此,则将其记录下来,然后必须有方法将字符串与编码一起传递。

0

我已经通过wifstream读取配置文件UTF8文件名(它使用为wchar_t缓冲)。

Mac实现与Linux和Windows不同。 wifstream从文件读取每个字节以将缓冲区中的wchar_t单元分隔开。所以我们有3个空字节,尽管打开要求char字符串。因此程序员可以使用wcstombs函数将宽字符串转换为多字节字符串。

该API支持UTF8。为了更好的理解,使用内存观察器和十六进制编辑器来处理文件