繁体   English   中英

在Mac OS X下等效的_wfopen

[英]_wfopen equivalent under Mac OS X

我期待在Mac OS X下相当于Windows _wfopen() 。任何想法?

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

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");

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

您只想使用可能包含Unicode字符的路径打开文件句柄,对吗? 只需将文件系统表示中的路径传递给fopen

  • 如果路径来自库存Mac OS X框架(例如,Open面板,无论是Carbon还是Cocoa),您将不需要对其进行任何转换,并且可以按原样使用它。

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

一般来说,对于大多数应用程序,您不必执行大量操作。 例如,许多应用程序可能将辅助数据文件存储在用户的Application Support目录中,但只要这些文件的名称是ASCII,并且您使用标准的Mac OS X API来查找用户的Application Support目录,就不需要了做一堆用这两个组件构造的路径的偏执转换。

编辑添加:我强烈建议不要使用类似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都可以避免在同一目录中放置具有相同名称(用户感知它们)的多个文件。

如何执行这种规范分解的规则可能非常繁琐,因此,不要试图自己实现它,最好将它留给系统框架为您提供的功能。

@JKP:

并非MacOS X中的所有函数都接受UTF8,但文件名和文件路径可能是UTF8,因此处理文件访问(open,fopen,stat等)的所有POSIX函数都接受UTF8。

看到这里 引用:

文件名在API级别的查看方式取决于API。 当前的Carbon API将文件名作为UTF-16字符数组处理; POSIX将它们作为UTF-8数组处理,这就是UTF-8在终端中运行良好的原因。 它如何存储在磁盘上取决于磁盘格式; HFS +使用UTF-16,但在大多数情况下这并不重要。

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

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

该函数只接受带有纯ASCII字符的C字符串(仅在0到126范围内)或者它将接受UTF8。 通常,函数不允许大于126的字符,并以UTF8以外的任何其他编码来解释它们。 如果确实如此,则记录在案,然后必须有一种方法将编码与字符串一起传递。

如果你正在使用Cocoa,使用NSString相当容易。 只需使用-initWithBytes:length:encoding :(或者可能是-initWithCString:encoding :)加载UTF16数据,然后通过在结果上调用UTF8String来获取UTF8版本。 然后,只需使用新的UTF8字符串作为参数调用fopen。

无论语言如何,你都可以使用UTF-8字符串调用fopen - 虽然对OSX上的C ++无法帮助 - 抱歉。

我通过wifstream从配置UTF8文件中读取文件名(它使用wchar_t缓冲区)。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM