none
basic_ifstreamの型 RRS feed

  • 質問

  • お世話になります。

    現在basic_ifstreamではまってしまっています。

    以下のような2種類のコードを書いてみました。

     

    日本語が混在したフォルダのファイル読み込み

      C:\Temp\てすとふぉるだ\test.txt

        内容:

                      163638    1737383     あいうえお

                      193838     893939      かきくけこ

                      983839     1838383    さしすせそ

                のような感じ。ディリミタはタブ。改行はLF。

    というファイル(中身はEUC)を読み込む際のコード

    コンパイルはUNICODEでコンパイルしています。

     

    // basic_ifstreamの型をTCHARにして読み込み

    bool func1(LPCTSTR lpPath)

    {
        std::basic_ifstream<TCHAR> aFile(lpPath);
        if (! aFile.is_open()) return false;

        aFile.imbue(std::locale("japanese"));
        TCHAR buff[BUFSIZ];

        while (aFile.getline(buff, BUFSIZ-1))
        {

            ....

        }

        return true;
    }

     

    bool func2(LPCTSTR lpPath)
    {
        std::ifstream aFile(CT2A(lpPath));  // charに修正
        if (! aFile.is_open()) return false;

        char buff[BUFSIZ];

        while (aFile.getline(buff, BUFSIZ-1))

        {

            ....
        }

        return true;
    }

     

    func1の方法ですと、getlineで数行読み込んだだけで、ファイルの終端まで到達する前にループを抜けてしまいます。

    func2の方法ですと、パスの日本語の部分が化けてしまってオープンできない症状が出てしまいます。

    どのようにすると正常に読み込みできる状態となりますでしょうか?

     

    よろしくお願いいたします。

     

    2007年12月26日 2:00

回答

  • >> だったらTCHARで取り込んじゃダメでしょ(UNICODEモードだとガタガタになるっしょ)。
    >> char決め打ちのifstreamからgetlineし、読み込んだchar[]を変換せんと。

    >

    > はい、それで、func2のような手法で実行してみたのですが、以下のような問題が発生している次第です。

    >  ・パスの日本語部分がstd::ifstreamのopenの中で文字化けし、正常なパスとされないため、失敗してしまう。

     

    てことはCT2Aがちゃんと変換してくれていないってことがはっきりしてますよね?

    - このときlpPathはUNICODEすなわち TCHAR = wchar_t ですか?
    - CT2Aの使い方、ホントにこれで正しいのですか? (僕は知りません、疑ってるんです)

     

    2007年12月26日 2:57

すべての返信

  • 確認/検証をお願いします。

    - 食わすファイルが日本語を含まないなら、ちゃんと読みますか?

    - 食わすファイルの日本語がShift_JISなら、ちゃんと読みますか?

     

    おそらくEUCを(コード変換を伴って)読ますのは困難ですよ。
    一旦読んでからShift_JISなりUnicodeに変換してあげないと。

     

    2007年12月26日 2:13
  • επιστημηさん、早速のご返信ありがとうございます。

     

    - 食わすファイルが日本語を含まないなら、ちゃんと読みますか?

     日本語を含まない場合は読めています。

     

    - 食わすファイルの日本語がShift_JISなら、ちゃんと読みますか?

     Shift_JISにした場合は、オープンはできますが、getlineでは1行も取ってくることができず、ループをそのまま素通りしてしまいます。

     

    - おそらくEUCを(コード変換を伴って)読ますのは困難ですよ。
      一旦読んでからShift_JISなりUnicodeに変換してあげないと。

     

    一応、getlineで取得後、EUCからShift_JISに変換するようなことは行っています。

     

    ちなみにですが、ファイルのパスに日本語を含まない場合は、func2の手法でも普通に読むことができています。しかし、この場合、func1の手法ですと、ファイル終端まで行かずにループを抜けてしまいます。

     

     

     

     

    2007年12月26日 2:28
  • > 一応、getlineで取得後、EUCからShift_JISに変換するようなことは行っています。

     

    だったらTCHARで取り込んじゃダメでしょ(UNICODEモードだとガタガタになるっしょ)。
    char決め打ちのifstreamからgetlineし、読み込んだchar[]を変換せんと。

     

    2007年12月26日 2:36
  • επιστημη さん、ご返信ありがとうございます。

     

    > だったらTCHARで取り込んじゃダメでしょ(UNICODEモードだとガタガタになるっしょ)。
    > char決め打ちのifstreamからgetlineし、読み込んだchar[]を変換せんと。

     

    はい、それで、func2のような手法で実行してみたのですが、以下のような問題が発生している次第です。

      ・パスの日本語部分がstd::ifstreamのopenの中で文字化けし、正常なパスとされないため、失敗してしまう。

       ⇒_Fiopen()の中のmbstowcs_s()でパスの日本語が化けてしまいます。

     

    恐れ入りますが、問題点について更にご指摘いただければ幸いです。

    よろしくお願いいたします。

     

    2007年12月26日 2:46
  • >> だったらTCHARで取り込んじゃダメでしょ(UNICODEモードだとガタガタになるっしょ)。
    >> char決め打ちのifstreamからgetlineし、読み込んだchar[]を変換せんと。

    >

    > はい、それで、func2のような手法で実行してみたのですが、以下のような問題が発生している次第です。

    >  ・パスの日本語部分がstd::ifstreamのopenの中で文字化けし、正常なパスとされないため、失敗してしまう。

     

    てことはCT2Aがちゃんと変換してくれていないってことがはっきりしてますよね?

    - このときlpPathはUNICODEすなわち TCHAR = wchar_t ですか?
    - CT2Aの使い方、ホントにこれで正しいのですか? (僕は知りません、疑ってるんです)

     

    2007年12月26日 2:57
  • > てことはCT2Aがちゃんと変換してくれていないってことがはっきりしてますよね?

     そうみたいでした。まだ若干問題があります(中の文字を一部正常に取ってくれない)が、一通り読むことができました。

     

    - このときlpPathはUNICODEすなわち TCHAR = wchar_t ですか?

     はい。そうです。


    - CT2Aの使い方、ホントにこれで正しいのですか? (僕は知りません、疑ってるんです)

     ちなみにですが、επιστημη さんはwchar_t*からchar*に変更するときってどのようにしていますか?

     差支えがなければ教えてください。

     

     

    2007年12月26日 3:08
  • > wchar_t*からchar*に変更するときってどのようにしていますか?

     

    方法はいくらもあるのでシチュエーションに応じて使い分けています。

     

    2007年12月26日 3:14
  • > 方法はいくらもあるのでシチュエーションに応じて使い分けています。

    そうですよねー。

     

    解決の糸口が見つかりましたので、助かりました。

    ありがとうございました。

     

     

    2007年12月26日 3:18
  • こんにちは、フォーラム オペレータ大久保です。

     

    επιστημη さん、いつもご利用ありがとうございます。

    さしつかえなければ、επιστημη さんならどう対応するか、一例でいいので教えていただけると皆さんの参考になると思うんですが…

    細かいシチュエーションがいろいろ考えられると思うので難しいとは思いますが、επιστημη さんがよく使うパターンがあればご紹介いただけませんか?

     

    kfsh さん、勝手とは思いましたが、επιστημη さんの回答が解決の糸口になったようなので、回答済みのチェックをつけさせていただきました。

    もし不適切でしたらチェックを解除することもできますのでご確認ください。

     

    それでは。

    2008年1月8日 8:25
  • > さしつかえなければ、επιστημη さんならどう対応するか、一例でいいので教えていただけると

    > 皆さんの参考になると思うんですが…

    > 細かいシチュエーションがいろいろ考えられると思うので難しいとは思いますが、

    > επιστημη さんがよく使うパターンがあればご紹介いただけませんか?

     

    えー、そいじゃ...

     

    1. shift_jis/UTF16/UTF8 のみ対応、VC++9, C++/CLI のとき

     → marshalling library

    2. いろんな文字コード、C++/CLI のとき
     → .NET Framework の Encoding族
    3. shift_jis/UTF16 のみ対応、nativeのとき
     → 標準 wcstombs/mbstowcsとlocaleのコンボ
    4. いろんな文字コード、nativeのとき
     → IBM製ICU

    などなど、そんなのを使ってます。

    2008年1月8日 10:33
  • επιστημη さん、さっそくありがとうございます!

     

    昔、個人的に cgi プログラムを書いていた頃、それまで文字コードの概念がそれほど必要でない世界でのプログラミング経験しかなかったため、大変苦労したことを思い出しました。

    いろいろな手法を使い分けることがポイントなんですね。参考になりました。

    私の場合は、まず文字コードについてもっと理解を深めることが必要ですが…

     

    貴重な情報をありがとうございました!

    2008年1月8日 10:43