環境: Win2000(SP4) VC++2005
下記のフォーラムを参考にして VC2005 でファイルを読み込み、その内容を表示するプロ
グラムを作成しました。
しかし正しく表示させることができず、困っております。
参考: http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=243152&SiteID=7
下記のプログラムを実行すると、123456 とだけ表示され、それ以降の日本語部分は表
示されません。
デバッガで追ってみたところ、ostream の << 演算子の処理で日本語部分が bad_bit と
判定されてしまったために表示されない模様です。
locale の設定をしなければ std::cout に日本語を出力することができますが、この場合
は ifstream を開くことができません。
以上は文字セットを Unicode 、マルチバイトのいずれにしても同様の結果になりました。
cahr* 型の日本語を含むパスでファイルを開き、さらに日本語をコンソール出力する方法
をご存知の方がおられましたら、ご教示ください。
-----------------------------------------------
#include <fstream>
#include <iostream>
#include <string>
#include <locale>
int _tmain(int argc, _TCHAR* argv[])
{
std::locale::global( std::locale( japanese ) );
const char* path = C:\\サンプル\\sample.txt;
std::cout << File open: ;
std::ifstream file_stream( path );
std::cout << file_stream.is_open() << std::endl;
std::string buffer;
while( std::getline( file_stream, buffer ) )
{
std::cout << buffer << std::endl;
}
return 0;
}
// 以下、C:\サンプル\sample.txt の内容
123456サンプル
なんか見たことあるぞ。
cout.imbue(locale(japanese));
とするとどうでしょうか?
類似スレ
http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=250724&SiteID=7
ん、ちがった。
>参考: http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=243152&SiteID=7
で私(蒼の洞窟)も書いていますが、
file_stream.imbue(std::locale(japanese));
ですかね。
Blue さん、ご回答いただきありがとうございます。
cout と file_stream の両方、またはどちらか一方に imbue(locale(japanese))
を設定しても、やはり結果は同じでした。
しかし、 locale::global を設定せずにファイルのパスを wchar_t* で与えてやると、
想定通りの出力を得られました。
# これって、標準規格にはない使い方のような……
「類似スレ」に書かれているとおり、バグなんでしょうか。
>std::locale::global( std::locale( japanese ) );
をなしで、
>cout と file_stream の両方、またはどちらか一方に imbue(locale(japanese))
>を設定
でも同じ結果でしたでしょうか?
std::locale::global( std::locale( japanese ) ); を削除した場合、
ファイルストリームを開くことができませんでした。
これは、ファイルストリームのロケール設定をした後で open() しても同様です。
また cout に対する文字列出力に絞って検証してみましたが、locale::global()
があると日本語が表示されず、これを削除した場合は imbue() 関数を使用するしない
に関わらず正常に出力されました。
余談ですが、デバッガで追いかけてみたところ、 locale::global() があれば
file_stream に imbue() しなくとも getline() で正しく文字列を読み込むことが
できるようです。
念のため、今回の検証で使用したコードも掲載しておきます。
-----------------------------------------------------
#include <fstream>
#include <iostream>
#include <string>
#include <locale>
int _tmain(int argc, _TCHAR* argv[])
{
// std::locale::global( std::locale( japanese ) ); //<- グローバルなロケール設定
std::cout.imbue( std::locale( japanese ) ); //<- 標準出力のロケール設定
const char* path = C:\\サンプル\\sample.txt;
std::cout << File open: ;
std::ifstream file_stream;
file_stream.imbue( std::locale( japanese ) ); //<- ファイルストリームのロ
ケール設定
file_stream.open( path );
std::cout << file_stream.is_open() << std::endl;
std::string buffer;
while( std::getline( file_stream, buffer ) )
{
std::cout << buffer << std::endl;
}
file_stream.close();
return 0;
}
http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=250724&SiteID=7
結局VC2005のバグのようです。(SP1でも改善されていないっぽい。)
リンク先に書いてあるように、
_setmode(_fileno(stdout), _O_BINARY);
とすることで、std::locale::global() をしても日本語が出力されるようになりました。
(こんどは改行の問題がありますが。)
> http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=250724&SiteID=7
あら、Blueさんがすでに挙げてましたね。
失礼しました。
isshi さん、ご回答ありがとうございます。
私の方でも、
_setmode(_fileno(stdout), _O_BINARY);
とすることで日本語が正しく出力されることを確認しました。
改行コードの問題は運用で回避できそうですので、この方法で対処したいと思います。
また Blue さんもお付き合いいただき、ありがとうございました。