質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.02%
Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

コンソールに日本語をキレイに出力したい

aglkjggg
aglkjggg

総合スコア769

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

3回答

0グッド

3クリップ

20410閲覧

投稿2017/05/01 13:56

編集2017/05/01 14:09

Ⅰ. やりたいこと

ファイルを読み込み、コンソールに日本語をキレイに出力したいです。

以下の画像が理想の出力です。

Ⅱ. 発生している問題

  • ファイル形式がUTF-8の場合

文字化けしてしまいます。

abc 縺 ゅ > 縺 ・ ∴ 縺

  • ファイル形式がShift-JIS の場合

日本語が表示されますが文字と文字の間に半角スペースと思われるものが入っています。
本当に半角スペースなのかは分かっていません。

aiueo あ い う え お

Ⅲ. プログラム

  • test.txt
abc あいうえお
  • Source.cpp

cpp

1int main() 2{ 3 // ファイルをすべて読み込む 4 ifstream ifs("test.txt"); 5 string str((istreambuf_iterator<char>(ifs)), istreambuf_iterator<char>()); 6 7 // 出力する 8 cout << str << endl; 9 10 return 0; 11}

Ⅳ. 試したこと

  • setlocale(LC_ALL, "ja_JP.UTF-8");

変化なし

  • std::wcout.imbue( std::locale( "", std::locale::ctype ) );

変化なし

  • setlocale( LC_CTYPE, "" );

変化なし

  • wchar_t にする

変化なし

cpp

1wifstream ifs("test.txt"); 2wstring str((istreambuf_iterator<wchar_t>(ifs)), istreambuf_iterator<wchar_t>()); 3wcout << str << endl;

Ⅴ. 環境

  • Windows 10 64bit Version 1703
  • Visual Studio 2017 (v141)

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答3

2

自己解決

Shift-JIS

cpp

1#include <iostream> 2#include <fstream> 3#include <string> 4 5ifstream ifs("shift-jis.txt"); 6string str((istreambuf_iterator<char>(ifs)), istreambuf_iterator<char>()); 7 8cout << str << endl;

UTF-8(BOMなし)

cpp

1#include <iostream> 2#include <fstream> 3#include <string> 4#include <codecvt> 5 6setlocale(LC_ALL, ""); 7 8wifstream ifs("UTF-8N.txt"); 9ifs.imbue(locale(locale::empty(), new codecvt_utf8<wchar_t>)); 10wstring str((istreambuf_iterator<wchar_t>(ifs)), istreambuf_iterator<wchar_t>()); 11 12wcout << str << endl;

UTF-8(BOMあり)

cpp

1#include <iostream> 2#include <fstream> 3#include <string> 4#include <codecvt> 5 6setlocale(LC_ALL, ""); 7 8wifstream ifs("UTF-8(BOM).txt"); 9ifs.imbue(locale(locale::empty(), new codecvt_utf8<wchar_t, 0x10ffff, consume_header>)); 10wstring str((istreambuf_iterator<wchar_t>(ifs)), istreambuf_iterator<wchar_t>()); 11 12wcout << str << endl;

UTF-16 リトルエンディアン (BOMなし)

cpp

1#include <iostream> 2#include <fstream> 3#include <string> 4#include <codecvt> 5 6setlocale(LC_ALL, ""); 7 8wifstream ifs("UTF-16LEN.txt"); 9ifs.imbue(locale(locale::empty(), new codecvt_utf16<wchar_t, 0x10ffff, little_endian>)); 10wstring str((istreambuf_iterator<wchar_t>(ifs)), istreambuf_iterator<wchar_t>()); 11 12wcout << str << endl

UTF-16 リトルエンディアン (BOMあり)

cpp

1#include <iostream> 2#include <fstream> 3#include <string> 4#include <codecvt> 5 6setlocale(LC_ALL, ""); 7 8wifstream ifs("UTF-16LE(BOM).txt"); 9ifs.imbue(locale(locale::empty(), new codecvt_utf16<wchar_t, 0x10ffff, consume_header>)); 10wstring str((istreambuf_iterator<wchar_t>(ifs)), istreambuf_iterator<wchar_t>()); 11 12wcout << str << endl;

UTF-16 ビッグエンディアン (BOMなし)

cpp

1#include <iostream> 2#include <fstream> 3#include <string> 4#include <codecvt> 5 6setlocale(LC_ALL, ""); 7 8wifstream ifs("UTF-16BEN.txt"); 9ifs.imbue(locale(locale::empty(), new codecvt_utf16<wchar_t>)); 10wstring str((istreambuf_iterator<wchar_t>(ifs)), istreambuf_iterator<wchar_t>()); 11 12wcout << str << endl;

UTF-16 ビッグエンディアン (BOMあり)

cpp

1#include <iostream> 2#include <fstream> 3#include <string> 4#include <codecvt> 5 6setlocale(LC_ALL, ""); 7 8wifstream ifs("UTF-16BE(BOM).txt"); 9ifs.imbue(locale(locale::empty(), new codecvt_utf16<wchar_t, 0x10ffff, consume_header>)); 10wstring str((istreambuf_iterator<wchar_t>(ifs)), istreambuf_iterator<wchar_t>()); 11 12wcout << str << endl;

投稿2017/05/02 02:38

編集2017/05/02 03:07
aglkjggg

総合スコア769

BeatStar, umyu👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

Chironian

2017/05/02 02:49 編集

すいません。気になるので1点教えてください。 「Shift-JIS」の内容は質問文の内容と特に変化がないようにみえますが、setlocale(LC_ALL, "");の書き忘れでしょうか? →あっと、can110さんへのコメントで理解しました。

1

Win10(1703)+VS2017で再現しました。
プロジェクトの文字セットはデフォルトの「Unicode文字セットを使用する」です。
よって、setlocaleではなく_tsetlocaleを呼び出すことで、こちらの環境では解消しました。
文字セットを切り替えないなら_wsetlocaleでも良いはずです。

追試

setlocale,_tsetlocale,_wsetlocaleいずれかを呼び出すと、こちらの環境では解消しました。
いずれも呼び出さないと再現します。

C++

1#include <iostream> 2#include <fstream> 3#include <string> 4using namespace std; 5int main() 6{ 7 _tsetlocale(LC_ALL, _T("")); 8 9 // ファイルをすべて読み込む 10 ifstream ifs(_T("test.txt")); 11 string str((istreambuf_iterator<char>(ifs)), istreambuf_iterator<char>()); 12 // 出力する 13 cout << str << endl; 14 return 0; 15}

投稿2017/05/02 00:49

編集2017/05/02 02:34
can110

総合スコア36356

umyu👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

Chironian

2017/05/02 02:19

プロジェクトの文字セットの設定は、明示的にnarrow文字列を使っている時には影響しないはずです。 でも、1703で再現し、setlocaleが必要ということは、1703で何か仕様が変わっていそうですね。 私のWindows 10は1607でした。
can110

2017/05/02 02:39

setlocaleは試していなかったですが、これでも解消しました。 ちょっと理由が分からない動きですが。。。 こちらでは1703未満の環境ないので確認できないのですが コマンドプロンプトの動作が変わったのかもしれませんね。
aglkjggg

2017/05/02 03:04 編集

ご回答ありがとうございます。 ■Shift-JIS について PCを再起動してもう一度確認した所半角スペースの様なものが出現するのは再現しなくなってしまいました。 再起動後もWindows 10 ver 1703 から変わっていませんでした。 (解決したのはいいのですが、なぜ半角スペースの様なものが出ていたのか原因が辿れなくなりました…) ■プロジェクトの文字セットについて プロジェクトの文字セットの内容にかかわらず同じ動作が確認できました。 プロジェクトの文字セットは今回の件とは関係ないようです。 ■_tsetlocale()について _tsetlocale には tchar.h が必要なようなので、 #include <tchar.h> を追加して試してみましたが結果的にUTF-8やUTF-16のようなunicodeの場合 _tsetlocale() だけでは不十分でwifstreamにimbueで明示的にロケールを設定する必要がありました。 また、こちらの環境でも上記のロケール設定に加えて、 setlocale, _tsetlocale, _wsetlocale のいずれかを呼び出せば解決しました。 自己解決という項目でまとめを投稿させていただきました。 (コメントではMarkdownが使えないので…)
can110

2017/05/02 03:44

自己回答について了解しました。 再起動により再現しなくなったとすると、コマンドプロンプト内部で保持している状態(設定)によって挙動が変わる感じですね。何だかもやもやしますが。

1

こんにちは。

ファイル形式がShift-JIS の場合

日本語が表示されますが文字と文字の間に半角スペースと思われるものが入っています。
本当に半角スペースなのかは分かっていません。

手元ではShift-JISなら文字化けしないし、文字と文字の間もあきませんでした。原理的にもShift-JISで入力し、Shift-JISで出力すれば文字化けしない筈です。test.txtの内容を確認されて見て下さい。

text

1abc 2あいうえお

wchar_tを使うならば、test.txtをUTF-16のリトルエンディアンで保存すれば文字化けしないはずです。
なぜなら、C++は自動的な文字コード変換には対応していません。
そして、Visual C++のwstringはUTF-16がデフォルトですので、UTF-16で保存しておけば適切に動作する筈です。
なお、この場合はstd::wcout.imbue(std::locale(""));が必要です。


先週、この辺の問題について記事を書きました。文字コードとVisual C++の悩み
もし、良かったら参考にして下さい。


【追記】
気になるので、wifstreamの動きをみてみました。
下記プログラムでUTF-16LEファイルを読ませると、wstringの1文字にファイル上の1バイトが読み出されていました。MinGW、および、ubuntu上のg++でも同様でした。
何も指定しない場合は、テキスト・ファイルがASCIIでエンコードされていると解釈して読み取る仕様のようです。

C++

1#include <fstream> 2#include <iostream> 3#include <string> 4#include <iomanip> 5using namespace std; 6 7int main() 8{ 9 setlocale(LC_ALL, ""); 10 wifstream ifs("test3.txt"); 11 wstring str((istreambuf_iterator<wchar_t>(ifs)), istreambuf_iterator<wchar_t>()); 12 wcout << str << endl; 13 14 wcout << endl << str.size() << endl; 15 for (auto i : str) 16 wcout << hex << (int)i << "\n"; 17 18 return 0; 19}

投稿2017/05/01 14:44

編集2017/05/02 03:33
Chironian

総合スコア23251

umyu👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

aglkjggg

2017/05/02 02:26 編集

ご回答ありがとうございます。 <s> Shift-JIS については、 「従来のコンソールを使う」のチェックが「オン」になっている場合期待通りの動作をしました。 「オフ」になっている場合は質問時の画像の様にスペースの様なものが入ります。 質問時のプログラムから変更はありません。 http://i.imgur.com/k6VU2Oo.png </s> すみません。 PCを再起動してもう一度確認した所チェックは関係ありませんでした。 半角スペースの様なものが出現するのは再現しなくなってしまいました。 (解決したのはいいのですが、なぜ半角スペースの様なものが出ていたのか原因が辿れなくなりました…) UTF-8については、 「従来のコンソールを使う」のチェックに関わらず期待通りの動作をしました。 プログラムは画像のとおりです。 http://i.imgur.com/Oq0C2uF.png UTF-16については、 UTF-16 リトルエンディアンのテキストファイルを用意してみましたが期待通りの動作をしませんでした。 以下の画像になってしまいました。 プログラムは画像のとおりです。 http://i.imgur.com/57xBKVF.png http://i.imgur.com/H0WDDBm.png
Chironian

2017/05/02 02:29

私のところでは、「従来のコンソールを使う」はOFFのままでした。 can110さんによると1703で再現したということですが、私のWindows 10は1607のため、再現しないと言うことかも知れません。 この辺の動きが1703で変わっているとしたら、今のところ私の方では確認できないです。 UTF-8でうまくいく件はcodecvtをimbueで指定したことないので、良く分かりません。
Chironian

2017/05/02 03:14

あと、どうもwifstreamの動作について私は思い込みがあったようです。すいません。 特になにも指定していないにも関わらず何か処理するようですね。

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.02%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。