web-dev-qa-db-ja.com

Unicode UTF-8ファイルをwstringに読み込む

WindowsプラットフォームでUnicode(UTF-8)ファイルをwstring(s)に読み込むにはどうすればよいですか?

36
Abdelwahed

C++ 11サポートを使用すると、 std :: codecvt_utf8 facetを使用できます。これは、UTF-8エンコードバイト文字列とUCS2またはUCS4文字列の間の変換をカプセル化しますおよびUTF-8ファイル(テキストとバイナリの両方)の読み取りと書き込みに使用できます。

ファセット を使用するには、通常、特定のローカライズを集合的に定義するファセットのセットとしてカルチャ固有の情報をカプセル化する ロケールオブジェクトを作成しますenvironment。ロケールオブジェクトを取得したら、それを使用してストリームバッファを imbue にできます。

#include <sstream>
#include <fstream>
#include <codecvt>

std::wstring readFile(const char* filename)
{
    std::wifstream wif(filename);
    wif.imbue(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>));
    std::wstringstream wss;
    wss << wif.rdbuf();
    return wss.str();
}

次のように使用できます。

std::wstring wstr = readFile("a.txt");

あるいは、文字列ストリームを操作する前に グローバルC++ロケール を設定して、今後std::localeグローバルC++ロケールのコピーを返すデフォルトのコンストラクター(ストリームバッファーに明示的に埋め込む必要はありません):

std::locale::global(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>));
32
LihO

@Hans Passantのコメントによると、最も簡単な方法は _ wfopen_s を使用することです。モード_rt, ccs=UTF-8_でファイルを開きます。

以下は、少なくともVC++ 2010で機能する別の純粋なC++ソリューションです。

_#include <locale>
#include <codecvt>
#include <string>
#include <fstream>
#include <cstdlib>

int main() {
    const std::locale empty_locale = std::locale::empty();
    typedef std::codecvt_utf8<wchar_t> converter_type;
    const converter_type* converter = new converter_type;
    const std::locale utf8_locale = std::locale(empty_locale, converter);
    std::wifstream stream(L"test.txt");
    stream.imbue(utf8_locale);
    std::wstring line;
    std::getline(stream, line);
    std::system("pause");
}
_

locale::empty()(ここではlocale::global()も機能する可能性があります)および_wchar_t*_コンストラクターの_basic_ifstream_オーバーロードを除き、これはかなり標準に準拠しているはずです( 「標準」はもちろんC++ 0xを意味します)。

14
Philipp

Windows専用のプラットフォーム固有の機能は次のとおりです。

size_t GetSizeOfFile(const std::wstring& path)
{
    struct _stat fileinfo;
    _wstat(path.c_str(), &fileinfo);
    return fileinfo.st_size;
}

std::wstring LoadUtf8FileToString(const std::wstring& filename)
{
    std::wstring buffer;            // stores file contents
    FILE* f = _wfopen(filename.c_str(), L"rtS, ccs=UTF-8");

    // Failed to open file
    if (f == NULL)
    {
        // ...handle some error...
        return buffer;
    }

    size_t filesize = GetSizeOfFile(filename);

    // Read entire file contents in to memory
    if (filesize > 0)
    {
        buffer.resize(filesize);
        size_t wchars_read = fread(&(buffer.front()), sizeof(wchar_t), filesize, f);
        buffer.resize(wchars_read);
        buffer.shrink_to_fit();
    }

    fclose(f);

    return buffer;
}

次のように使用します:

std::wstring mytext = LoadUtf8FileToString(L"C:\\MyUtf8File.txt");

ファイル全体がメモリにロードされるので、非常に大きなファイルには使用したくない場合があります。

6
AshleysBrain
#include <iostream>
#include <fstream>
#include <string>
#include <locale>
#include <cstdlib>

int main()
{
    std::wifstream wif("filename.txt");
    wif.imbue(std::locale("zh_CN.UTF-8"));

    std::wcout.imbue(std::locale("zh_CN.UTF-8"));
    std::wcout << wif.rdbuf();
}
3
Shen Yu

この質問は C++のstd :: wstring、UTF-16、UTF-8、およびWindows GUIでの文字列の表示について混乱 で対処されました。要するに、wstringは、UTF-16の前身であるUCS-2標準に基づいています。これは厳密に2バイトの標準です。これはアラビア語にも当てはまると思います。

0
ThomasMcLeod