Unicode ファイル名で std::fstream (ofstream または ifstream) を開くにはどうすればよいですか?
質問
Windows アプリケーションの C++ 標準ライブラリを使用してファイルを開くことが、これほど基本的なことであるとは想像もできないでしょう...しかし、そうであるようです。ここで Unicode とは UTF-8 を意味しますが、UTF-16 などに変換することもできます。重要なのは、Unicode ファイル名から ofstream インスタンスを取得することです。独自のソリューションをハックする前に、ここで推奨されるルートはありますか?特にクロスプラットフォームのものですか?
解決
C ++標準ライブラリはUnicodeに対応していません。 char
および wchar_t
はUnicodeエンコードである必要はありません。
Windowsでは、 wchar_t
はUTF-16ですが、標準ライブラリではUTF-8ファイル名を直接サポートしていません(Windowsでは char
データ型はUnicodeではありません)
MSVC(およびMicrosoft STL)では、 const wchar_t *
ファイル名を取るファイルストリームのコンストラクターが提供され、次のようにストリームを作成できます。
wchar_t const name[] = L"filename.txt";
std::fstream file(name);
ただし、このオーバーロードはC ++ 11標準では指定されていません( char
ベースのバージョンの存在のみを保証します)。バージョンg ++ 4.8.xの時点で、MinGW(-w64)用のGCCのlibstdc ++などの代替STL実装にも存在しません。
Windowsの char
はUTF8ではなく、他のOSの wchar_t
はUTF16ではない可能性があることに注意してください。全体として、これは移植性が高いとは言えません。 wchar_t
ファイル名を指定してストリームを開くことは標準に従って定義されていません。また、charで使用されるエンコーディングはOSによって異なるため、 char
s es。
他のヒント
現在のバージョンのVisual C ++ std :: basic_fstreamには、
C ++ 17以降、 std :: filesystem :: path オーバーロード。 C ++ 20までは、を使用してUTF-8文字列からパスを作成できます。 std :: filesystem :: u8path 。例:
std::ofstream out(std::filesystem::u8path(u8"こんにちは"));
out << "hello";
C ++ 20の後、UTF-8をコンストラクターに渡すことでパスを作成できます: std :: filesystem :: path(u8&quot;&#12371;&#12435;&#12395;&# 12385;&#12399;&quot;)
(u8pathは非推奨になります)。
std :: wofstream
、 std :: wifstream
、および std :: wfstream
を使用します。 Unicodeファイル名を受け入れます。ファイル名は、 wstring
、 wchar_t
sの配列、または _T()
マクロ、またはプレフィックス L
テキストの前。
Boost.Nowide をご覧ください:
#include <boost/nowide/fstream.hpp>
#include <boost/nowide/cout.hpp>
using boost::nowide::ifstream;
using boost::nowide::cout;
// #include <fstream>
// #include <iostream>
// using std::ifstream;
// using std::cout;
#include <string>
int main() {
ifstream f("UTF-8 (e.g. ß).txt");
std::string line;
std::getline(f, line);
cout << "UTF-8 content: " << line;
}
Qt を混合して使用している場合 std::ifstream
:
return std::wstring(reinterpret_cast<const wchar_t*>(qString.utf16()));