2008-08-15 78 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。爲了更好的理解,使用內存觀察器和十六進制編輯器來處理文件