WinXPシステムで英語以外の名前のファイル名を処理するためのプログラミングを始めたばかりです。私はユニコードでいくつかの推奨読書をしました、そして私は基本的なアイデアを得ると思いますが、いくつかの部分はまだ私にはあまり明確ではありません。
具体的には、NTFSに保存されているファイル名前(コンテンツではなく、実際のファイル名)がどのエンコーディング(UTF-8、UTF-16LE/BE)ですか? char *を取るfopen()を使用してファイルを開くことは可能ですか、またはwchar_t *を使用し、おそらくUTF-16文字列を取るwfopen()を使用する以外に選択肢はありませんか?
UTF-8でエンコードされた文字列をfopen()に手動で入力しようとしました。
unsigned char filename[] = {0xEA, 0xB0, 0x80, 0x2E, 0x74, 0x78, 0x74, 0x0}; // 가.txt
FILE* f = fopen((char*)filename, "wb+");
しかし、これは「ê°€.txt」として出てきました。
Windowsアプリケーションを(wchar_t *)ではなく(char *)で渡していることを漠然と覚えているため、Windowsでファイル名を開くのにUTF8エンコードされた文字列で十分だという印象を受けました問題はありません。
誰もこれに光を当てることができますか?
NTFSはファイル名をUTF-16で保存しますが、fopen
はANSI(UTF-8ではありません)を使用しています。
UTF16エンコードされたファイル名を使用するには、Unicodeバージョンのファイルオープンコールを使用する必要があります。これを行うには、プロジェクトでUNICODE
と_UNICODE
を定義します。次に、CreateFile
呼び出しまたはwfopen
呼び出しを使用します。
fopen()-Windows上のMSVCでは、(デフォルトで)utf-8エンコードされたchar *を取りません。
残念なことに、utf-8は、ものごとのすばらしい計画のなかでかなり最近発明されました。 Windows APIは、UnicodeバージョンとAnsiバージョンに分かれています。 every文字列を取得または処理するWindows APIは、実際にはWまたはAの接尾辞で使用可能です-「ワイド」文字/ Unicodeの場合はW、Ansiの場合はAマクロマジックはこれをすべて開発者から隠しているので、違いを知らずに、ビルド構成に応じてchar *またはwchar_t *でCreateFileを呼び出すだけです。
「Ansi」エンコーディングは、実際には特定のエンコーディングではありません。ただし、「char」文字列に使用されるエンコーディングは、PCのロケール設定に固有であることを意味します。
現在、fopenのようなc-runtime関数は、開発者の知識がなくてもデフォルトで動作する必要があるため、Windowsシステムでは、Windowsローカルエンコーディングで文字列を受け取ることを期待しています。 msdnは、Microsoft c-runtime api setlocalが現在のスレッドのロケールを変更できることを示しますが、utf-8のように、1文字あたり2バイトを超えるロケールを必要とする場合は特に失敗します。
そのため、Windowsにはショートカットはありません。 必要 wfopenを使用するか、ネイティブAPI CreateFileW(またはUnicodeビルド設定を使用してプロジェクトを作成し、Createfileを呼び出すだけ)をwchar_t *文字列で使用します。
他の人が答えたように、UTF-8でエンコードされた文字列を処理する最良の方法は、それらをUTF-16に変換し、_wfopen
やCreateFileW
などのネイティブUnicode APIを使用することです。
ただし、Unicodeをサポートしていないか、ポータブルCで記述されているため、fopen()
を無条件に使用するライブラリを呼び出す場合、この方法は役に立ちません。その場合でも、レガシーを使用することは可能です。 UTF-8でエンコードされた文字列をfopen
で使用可能なASCII形式に変換するための「短いパス」ですが、いくつかの作業が必要です:
MultiByteToWideChar
を使用して、UTF-8表現をUTF-16に変換します。
GetShortPathNameW
を使用して、ASCIIのみの「ショートパス」を取得します。 GetShortPathNameW
は、すべてのASCIIコンテンツを含むワイド文字列として返します。これは、各wchar_t
char
をキャストするロスレスコピーによって、それを狭い文字列に簡単に変換する必要があります。
fopen()
または最終的にfopen()
を使用するコードに短いパスを渡します。そのコードによって出力されるエラーメッセージがある場合は、見苦しい「短いパス」(たとえば、KINTO~1
ではなくkinto-un-筋斗雲
)を参照することに注意してください。
これは厳密に推奨される長期戦略ではありませんが、Windowsの短いパスはボリュームごとにオフにできるレガシー機能であるため、fopen()
を使用するコードにファイル名を渡す唯一の方法である可能性がありますおよびその他のファイル関連のAPI呼び出し(stat
、access
、CreateFile
のANSIバージョンなど)。