fopen
Unicode 文字列ファイル パスを使用する標準的な方法はありますか?
4 に答える
いいえ、標準的な方法はありません。オペレーティング システムによっていくつかの違いがあります。さまざまな OS が非 ASCII ファイル名を処理する方法を次に示します。
Linux
Linux では、ファイル名は単なるバイナリ文字列です。最新のディストリビューションの慣習では、ASCII 以外のファイル名には UTF-8 を使用します。しかし当初は、ファイル名を ISO-8859-1 としてエンコードするのが一般的でした。エンコーディングの選択は基本的に各アプリケーション次第なので、同じファイルシステムで異なるエンコーディングを使用することもできます。環境変数はLANG
、優先エンコーディングが何であるかのヒントを与えることができます。しかし、最近では、おそらくどこでも UTF-8 を想定することができます。
ただし、これには問題がないわけではありません。無効な UTF-8 シーケンスを含むファイル名は、ほとんどの Linux ファイルシステムで完全に有効であるためです。UTF-8 しかサポートしていない場合、そのようなファイル名をどのように指定しますか? 理想的には、UTF-8 とバイナリ ファイル名の両方をサポートする必要があります。
OS X
OS X の HFS ファイルシステムは、内部で Unicode (UTF-16) ファイル名を使用します。ほとんどの C (および POSIX) ライブラリ関数はfopen
、UTF-8 文字列を受け入れ (8 ビット互換であるため)、内部で変換します。
ウィンドウズ
Windows API はファイル名に UTF-16 をfopen
使用しますが、それが何であれ現在のコードページを使用します (UTF-8 がオプションになりました)。wchar_t
多くの C ライブラリ関数には、UTF-16 ( Windows の場合)を受け入れる非標準の同等関数があります。たとえば、_wfopen
代わりにfopen
.
これは、現在のロケールの問題です。Unicode 対応の私のシステムでは、ファイル パスは Unicode になります。locale コマンドを使用してこれを検出できます。
$ locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
通常、ファイル パスのエンコーディングはシステム全体で設定されるため、ファイル パスがシステムのロケールにない場合は、おそらくiconvライブラリ を使用して変換する必要があります。
現在、ほぼすべての POSIX プラットフォームで UTF-8 が使用されています。また、最新の Windowsはロケールとして UTF-8 もサポートしています。どこでも UTF-8 を使用でき、Windows ではワイド文字列を使用せずに任意のファイルを開くことができます。fopen
ポータブルに動作します
setlocale(LC_ALL, "en_us.utf8"); // need some setup before calling this
fopen(R"(C:\filê\wíth\Ünicode\name.txt)", "w+");
Windows 10 ビルド 17134 (April 2018 Update) 以降、ユニバーサル C ランタイムは UTF-8 コード ページの使用をサポートします。これは、
char
C ランタイム関数に渡される文字列は、UTF-8 エンコーディングの文字列を想定していることを意味します。UTF-8 モードを有効にするには、 を使用する".UTF8"
ときにコード ページとして を使用しsetlocale
ます。たとえばsetlocale(LC_ALL, ".UTF8")
、現在の既定の Windows ANSI コード ページ (ACP) をロケールに使用し、UTF-8 をコード ページに使用します。...
Windows 7 など、Windows 10 より前の OS でこの機能を使用するには、アプリローカル展開を使用するか、Windows SDK のバージョン 17134 以降を使用して静的にリンクする必要があります。17134 より前の Windows 10 オペレーティング システムでは、静的リンクのみがサポートされています。