2017-04-12 1 views
1

私はファイルを持っていて、行末はウィンドウのスタイルです。\r\n; USC-2リトルエンディアンでエンコードされています。USC-2リトルエンディアンをUTF-8に正しく変換する方法は?

(USC-2リトルエンディアン)これはfruit.txt私のファイルであると言う:

input file

だから私はstd::wifstreamで開き、内容を解析してみてください:

// open the file 
    std::wifstream file("fruit.txt"); 
    if(! file.is_open()) throw std::runtime_error(std::strerror(errno)); 

// create container for the lines 
    std::forward_list<std::string> lines; 

// Add each line to the container 
    std::wstring line; 
    while(std::getline(file,line)) lines.emplace_front(wstring_to_string(line)); 

た場合、私は試しに試してみてください...

// Printing to cout 
    for(auto it = lines.cbegin(); it != lines.cend(); ++it) 
     std::cout << *it << std::endl; 

...これは出力です:

Cherry 
Banana 
ÿþApple 

さらに悪いことに、私はメモ帳++で開く場合は、まだ、これはそれが

Null characters everywhere

ように私は、ソートのことで、これを是正することができますに見えるものです強制的に戻す符号変換USC-2本になる:

enter image description here

マイwstring_to_string機能を

std::string wstring_to_string(const std::wstring& wstr) { 
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert; 
    return convert.to_bytes(wstr); 
} 

ここでは何が起こっているのですか?どのようにして通常のUTF-8文字列を取得できますか?私もこの方法を試しました:How to read utf-16 file into utf-8 std::string line by lineしかしstd::wifstreamの最初の結果は全く出力がありません。誰かがUSC-2 LEデータを読みやすいUTF-8データに変換する最善の方法で私に指示してくれますか?

編集 MSYS2が提供するmingw64/mingw-w64-x86_64-gcc 6.3.0-2のバグがあると思います。私はみんなの提案を試して、ストリームにロケールを埋め込むだけでは出力が全くないだけです。私は "C"と "POSIX"という2つのネイティブロケールしか用意されていないことを知っています。私はVisual Studioを試しましたが、4GBのダウンロードには十分なインターネット速度がありません。 @Andrei R.のようなICUを使用しましたが、それは素晴らしいです。

私は標準ライブラリを使うのが好きでしたが、これで大丈夫です。このソリューションが必要な場合は、私のコードを見てください:https://pastebin.com/qudy7yva

+0

このWindowsですか?コンソールテキストをエディタにコピーしてNP ++の画像を取得しましたか? (そして、誰かがNP ++がWindowsプログラムであると発言する前に、Wine上でうまく動作します) – deviantfan

+0

はい、これはWindowsです。 ./program.exe> log.txtのように私のプログラムを実行してlog.txtを取得しました。私はMSYS2のg ++​​ 6.3.0を使用しています –

+1

Windowsコンソール(すべてのバージョンのWindows用)ではUTF8を処理できないことがわかります。いくつかの事柄は回避策がありますが、100%の正しい動作は不可能です(例えば、CRTバグのために修正するつもりがない(作業が多すぎるためなど))。 >リダイレクトはあなた自身のプログラムの一部ではないので、あまりにもそれに頼ることはありません。 – deviantfan

答えて

0

ユニコードとの変換は一般的ではありません。 ICUライブラリを見て、私はこれがはるかに完全なc/C++の変換ライブラリをエンコードしていると信じています。

WideCharToMultibyte (Win)またはiconv (Linux)のようなプラットフォームに依存する方法もあります。 Qtでは、QString::fromUtf16を使用できます。おそらく、自分でエンディアンを逆転させる必要があります。

+1

' unicodeへの/からの変換は一般的ではありません.'これは変換ですUnicodeからUnicodeへ... ICUなしで管理可能 – deviantfan

1

コード自体はそのままです。

本当の問題は、入力ファイルが有効でないことです(std::codecvt_utf8_utf16にはUCS-2ではなくUTF-16が必要です)。これはNotepad ++のスクリーンショットにはっきりと示されています。

ぶっきらぼうは、ファイルデータはUCS-2BEの端にそのままを付加した(ÿþが8ビットANSIとして見たときにUTF-16LE BOMである)BOMを持つUTF-16LEファイルのように見える(またはUTF-16BE)ファイルにはBOMがありませんでした。

入力ファイルを修正して、ファイル全体がUTF-16LEの最初から最後まで有効になるようにする必要があります。

あなたが既に持っているコードは動作します。

+1

'本当の問題は、あなたの入力ファイルがNotepad ++ screenshots'にはっきりと示されていないことです。スクリーンショットは出力からのものだと思います。 – deviantfan

+1

私は 'fruit.txt' –

+0

のスクリーンショットで自分の答えを編集しました。新しいスクリーンショット(今回は入力済み)はOKです。 – deviantfan

0

あなたのケースでは、主な問題は、wifstreamを誤った方法でファイルを読み取らせたことです。 wstr_to_stringにwstrのサイズを表示すると、期待通りのものではないことがわかります。

https://stackoverflow.com/a/19698449/4005852

設定し、適切なロケールがこの問題を修正します。

std::string wstring_to_string(const std::wstring& wstr) { 
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert; 
    return convert.to_bytes(wstr); 
} 

int main() 
{ 
// open the file 
    std::wifstream file("fruit.txt", std::ios::binary); 
    file.imbue(std::locale(file.getloc(), 
      new std::codecvt_utf16<wchar_t, 0x10ffff, std::little_endian>)); 
    if(! file.is_open()) throw std::runtime_error(std::strerror(errno)); 

// create container for the lines 
    std::forward_list<std::string> lines; 

// Add each line to the container 
    std::wstring line; 
    file.get(); // remove BOM 
    while(std::getline(file,line)) lines.emplace_front(wstring_to_string(line)); 

// Printing to cout 
    for(auto it = lines.cbegin(); it != lines.cend(); ++it) 
     std::cout << *it << std::endl; 

    return 0; 
} 
+0

私はそれから全くアウトプットを得ていません。私はこれをコンパイラのバグと思っています。/ –

+0

"Microsoft(R)C/C++最適化コンパイラのバージョン19.00.24210 for x64"を使用しています。あなたのコンパイラは何ですか? –

+0

私は現在、Visual Studioをダウンロードして別のコンパイラを試しています。私は通常g ++をMSYS2から使います –

関連する問題