2011-01-23 24 views
25

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

+0

あなたはUTF-8またはUTF-16を意味していますか?そして、あなたはどんなプラットフォームを使っていますか? – dan04

+0

utf-8 on windows – Abdelwahed

+2

この記事を読む:[UTF-8をC++ストリームで読む](http://www.codeproject。 – Nawaz

答えて

0

この質問はConfused about C++'s std::wstring, UTF-16, UTF-8 and displaying strings in a windows GUIで解決されました。まとめると、wstringはUTF-16の前身であるUCS-2標準に基づいています。これは厳密に2バイトの標準です。私はこれがアラビア語をカバーすると信じている。

+1

私はあなたがUTF-16でwstringを使うことができると思います –

+0

@Daivd:あなたは間違っています。これはよくある誤解です。 UTF-16は、0〜0x10FFFFまでの1,112,064コードポイントをカバーします。この方式では、1つまたは2つの16ビットワードの可変長記憶が必要ですが、UCS-2は厳密に1つの16ビットワードです。定義wchar_tをトレースバックすると、ルートとして16ビットの基本型(通常はshort)があることがわかります。 – ThomasMcLeod

+1

@David:技術的には、 'wstring'はWindows上の単なる16ビット整数の配列です。 UCS-2またはUTF-16データなど、好きなものを格納できます。ほとんどのWindows APIは、今日はUTF-16文字列を受け入れます。 – Philipp

4

ここでは、Windowsのみのプラットフォーム固有の機能です:あなたはそれを使用したくない場合がありますので、ファイル全体が、メモリにロードされ

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

注:そうのような

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

使用して非常に大きなファイルの場合

+3

また、全体の方法を行くかもしれません:_wfopen(filename.c_str()、L "rt、ccs = UTF-8");変換は自動的になりました。 –

+0

ありがとう、編集された答え。 – AshleysBrain

+0

実際には、それをロールバックし、_wfopen上のドキュメントは自動的にワイド文字に変換し、このコードはそれを考慮に入れません。 – AshleysBrain

12

@Hans Passantのコメントによれば、最も簡単な方法は_wfopen_sです。モードrt, ccs=UTF-8でファイルを開きます。ここで

は少なくともVC++ 2010で動作する別の純粋なC++のソリューションです:locale::empty()を除き

#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::global()が同様に働くかもしれない)とbasic_ifstreamコンストラクタのwchar_t*過負荷、これでもかなりする必要があります標準に準拠しています(「標準」はC++ 0xを意味します)。 C++ 11のサポートにより

+5

なぜあなたは 'コンバータを削除しないのですか? – Mikhail

+1

"オーバーロード7は通常、新しい式から直接取得された第2引数fを使用して呼び出されます。ロケールは、それ自身のデストラクタから一致する削除を呼び出す責任があります。 [link](http://en.cppreference.com/w/cpp/locale/locale/locale) – sven

+0

これはファイルの最初の行だけを読み込みます.. –

20

、あなたは両方、UTF-8のファイルを読み書きするために使用することができUTF-8でエンコードされたバイト文字列とUCS2またはUCS4文字列と間の変換をカプセル化したstd::codecvt_utf8 facetを使用することができますテキストとバイナリです。あなたは通常、総称して、特定のローカライズされた環境を定義するファセットのセットとしてカルチャ固有の情報をカプセル化しlocale objectを作成facet使用するためには

。あなたは、ロケールオブジェクトを持っていたら、あなたはそれをあなたのストリームバッファを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"); 

あなたは、文字列ストリームを使用して作業する前に別の方法としては、the global C++ localeを設定できますは、std::localeデフォルトコンストラクタへの今後のすべての呼び出しで、グローバルC++ロケールのコピーを返します(この場合、ストリームバッファを明示的に埋め込む必要はありません)。

std::locale::global(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>)); 
+1

'new codecvt_utf8'に対応する' delete'が必要ですか? –

+0

codecvt_utf8を明示的に削除する必要はありません。これは、codecvt_utf8のrefcounterがゼロになるとstd :: localeのデストラクタで行われます(http://en.cppreference.com/w/cpp/locale/locale/%7Elocale参照) – MrTux

-3

これは少し生ではありませんが、ファイルを普通の古いバイトとして読み取ってから、バイトバッファをwchar_t *にキャストする方法はありますか?

ような何か: "ユニコード" と

#include <iostream> 
#include <fstream> 
std::wstring ReadFileIntoWstring(const std::wstring& filepath) 
{ 
    std::wstring wstr; 
    std::ifstream file (filepath.c_str(), std::ios::in|std::ios::binary|std::ios::ate); 
    size_t size = (size_t)file.tellg(); 
    file.seekg (0, std::ios::beg); 
    char* buffer = new char [size]; 
    file.read (buffer, size); 
    wstr = (wchar_t*)buffer; 
    file.close(); 
    delete[] buffer; 
    return wstr; 
} 
1
#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(); 
} 
+0

こんにちは。共有してくれてありがとう。感謝。もう少しコンテキストを追加できますか?なぜこの6年間の質問への答え。ありがとう。 – wp78de

+0

私は最近、いくつかの質問がありますが、私は今解決した、私は他の人を助けるために私のソリューションを共有したい。 –

+0

いいですね。しかし、あなたの答えは@ LihOの答えとどう違うのですか?別のロケールを使うだけですよね? – wp78de

関連する問題