_wfopen()
Mac OS Xでの Windows に相当するものを探しています。何か考えはありますか?
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 フレームワーク (たとえば、Carbon または Cocoa の Open パネル) からのものである場合、パスを変換する必要はなく、そのまま使用できます。
パスの一部を自分で生成している場合は、パスから CFStringRef を作成し、それをファイルシステム表現で取得して、open
や などの POSIX API に渡す必要がありますfopen
。
一般的に言えば、ほとんどのアプリケーションではそれほど多くのことを行う必要はありません。たとえば、多くのアプリケーションでは、補助データ ファイルがユーザーの Application Support ディレクトリに保存されている場合がありますが、それらのファイルの名前が ASCII であり、標準の Mac OS X API を使用してユーザーの Application Support ディレクトリを見つける限り、必要はありません。これらの2つのコンポーネントで構築されたパスのパラノイド変換の束を実行します。
追加するために編集:ファイルシステムのエンコーディングは生成されたUTF-8と必ずしも同一ではないため、次のようなものを使用してすべてを任意にUTF-8に変換しないように 強く警告します。wcstombs
Mac OS X と Windows はどちらも、ファイルシステム パスで使用されるエンコーディングに特定の (ただし異なる) 正規分解規則を使用します。
たとえば、"é" を 1 つまたは 2 つのコード単位として格納するかどうかを決定する必要があります (LATIN SMALL LETTER E WITH ACUTE
またはLATIN SMALL LETTER E
後に続くCOMBINING ACUTE ACCENT
)。これらは 2 つの異なる (そして長さの異なる) バイト シーケンスになり、Mac OS X と Windows はどちらも、同じ名前 (ユーザーが認識する) を持つ複数のファイルを同じディレクトリに配置しないように機能します。
この標準的な分解を実行する方法のルールは非常に複雑になる可能性があるため、自分で実装しようとするよりも、システム フレームワークが提供する機能に任せて、面倒な作業を行うのが最善です。
@JKP:
MacOS X のすべての関数が UTF8 を受け入れるわけではありませんが、ファイル名とファイルパスは UTF8 である可能性があるため、ファイル アクセスを扱うすべての POSIX 関数 (open、fopen、stat など) は 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 文字 (0 から 126 の範囲のみ) を含む C 文字列のみを受け入れるか、UTF8 を受け入れます。通常、関数は 126 を超える文字を許可せず、UTF8 以外のエンコードで解釈します。これが実際にあった場合は文書化されており、文字列とともにエンコーディングを渡す方法が必要です。
Cocoa を使用している場合は、NSString を使用するとかなり簡単です。-initWithBytes:length:encoding: (またはおそらく -initWithCString:encoding:) を使用して UTF16 データをロードし、結果に対して UTF8String を呼び出して UTF8 バージョンを取得します。次に、新しい UTF8 文字列をパラメータとして fopen を呼び出すだけです。
言語に関係なく、UTF-8 文字列で fopen を確実に呼び出すことができます - ただし、OSX 上の C++ では役に立ちません - 申し訳ありません。