日本語パスのファイルを開き、その内容を出力する方法

[戻る]
guicheng 2007/03/09(金) 11:45:39
環境: 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サンプル

Blue 2007/03/09(金) 11:55:20
なんか見たことあるぞ。

cout.imbue(locale("japanese"));

とするとどうでしょうか?

類似スレ
http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=250724&SiteID=7

Blue 2007/03/09(金) 12:01:24
ん、ちがった。

>参考:http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=243152&SiteID=7
で私(蒼の洞窟)も書いていますが、

file_stream.imbue(std::locale("japanese"));

ですかね。

guicheng 2007/03/09(金) 13:59:45
Blue さん、ご回答いただきありがとうございます。

cout と file_stream の両方、またはどちらか一方に imbue(locale("japanese")) 
を設定しても、やはり結果は同じでした。

しかし、 locale::global を設定せずにファイルのパスを wchar_t* で与えてやると、
想定通りの出力を得られました。
# これって、標準規格にはない使い方のような……

「類似スレ」に書かれているとおり、バグなんでしょうか。

Blue 2007/03/09(金) 14:06:17
>std::locale::global( std::locale( "japanese" ) );
をなしで、

>cout と file_stream の両方、またはどちらか一方に imbue(locale("japanese")) 
>を設定
でも同じ結果でしたでしょうか?

guicheng 2007/03/09(金) 17:17:14
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;
}

isshi 2007/03/13(火) 13:25:11
http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=250724&SiteID=7
結局VC2005のバグのようです。(SP1でも改善されていないっぽい。)

リンク先に書いてあるように、

_setmode(_fileno(stdout), _O_BINARY);

とすることで、std::locale::global() をしても日本語が出力されるようになりました。
(こんどは改行の問題がありますが。)

isshi 2007/03/13(火) 13:29:08
>http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=250724&SiteID=7
あら、Blueさんがすでに挙げてましたね。
失礼しました。

guicheng 2007/03/13(火) 15:44:45
[[解決]]
isshi さん、ご回答ありがとうございます。
私の方でも、

_setmode(_fileno(stdout), _O_BINARY);

とすることで日本語が正しく出力されることを確認しました。
改行コードの問題は運用で回避できそうですので、この方法で対処したいと思います。

また Blue さんもお付き合いいただき、ありがとうございました。

古いスレッドには追加発言できません。