簡體   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