[英]_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,如open
或fopen
。
一般來說,對於大多數應用程序,您不必執行大量操作。 例如,許多應用程序可能將輔助數據文件存儲在用戶的Application Support目錄中,但只要這些文件的名稱是ASCII,並且您使用標准的Mac OS X API來查找用戶的Application Support目錄,就不需要了做一堆用這兩個組件構造的路徑的偏執轉換。
編輯添加:我強烈建議不要使用類似wcstombs
東西任意將所有內容轉換為UTF-8,因為文件系統編碼不一定與生成的UTF-8相同。 Mac OS X和Windows都對文件系統路徑中使用的編碼使用特定(但不同)的規范分解規則。
例如,他們需要決定是否將“é”存儲為一個或兩個代碼單元( LATIN SMALL LETTER E WITH ACUTE
或LATIN 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.