web-dev-qa-db-ja.com

Unicodeファイル名でstd :: fstream(ofstreamまたはifstream)を開く方法は?

Windowsアプリケーション用のC++標準ライブラリを使用してファイルを開くのは難しいので、基本的なことを想像することはできませんが...ここでUnicodeとはUTF-8を意味しますが、UTF-16などに変換できますが、ポイントはUnicodeファイル名からofstreamインスタンスを取得することです。自分のソリューションをハックする前に、ここに優先ルートはありますか?特にクロスプラットフォームのものですか?

49

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以降、GCCのMinGW(-w64)用libstdc ++のような代替STL実装にも存在しません。

WindowsのcharはUTF8ではなく、他のOSのwchar_tはUTF16ではない可能性があることに注意してください。全体として、これは移植性が高いとは言えません。 wchar_tファイル名を指定してストリームを開くことは標準に従って定義されていません。また、charsでファイル名を指定することは、charによって使用されるエンコーディングがOSによって異なるため難しい場合があります。

56
jalf

C++ 17以降、 std :: filesystem :: path オーバーロードを使用してUnicodeファイル名でstd :: fstreamを開くクロスプラットフォームの方法があります。 C++ 20までは、 std :: filesystem :: u8path でUTF-8文字列からパスを作成できます。例:

_std::ofstream out(std::filesystem::u8path(u8"こんにちは"));
out << "hello";
_

C++ 20以降では、UTF-8をコンストラクターに渡すことでパスを作成できます:std::filesystem::path(u8"こんにちは")(u8pathは非推奨になります)。

6
Nikolai

Visual C++の現在のバージョンであるstd :: basic_fstreamには、 http://msdn.Microsoft.com/en-us/library/4dx08bh4に従ってwchar_t *をとるopen()メソッドがあります。 aspx

3
John Downey

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;
}
1
jhasse

_std::wofstream_、_std::wifstream_、および_std::wfstream_を使用します。 Unicodeファイル名を受け入れます。ファイル名はwstring、_wchar_t_ sの配列、または_T()マクロ、またはテキストの前にLを付ける必要があります。

1
Brackets

Qtをstd::ifstreamと混合して使用している場合:

return std::wstring(reinterpret_cast<const wchar_t*>(qString.utf16()));
1