• ベストアンサー

fgetws関数で読み込んだUNICODE文字列の文字化け

お世話になります。 UNICODE文字列について上手くいかない部分があったので質問します。 (1)ANSI文字コードのテキストファイルをfgetws関数で読み込む (2)読み込んだ文字列をID3DXFont::DrawTextWメソッドで描画 以上のことを行うと、1バイト文字(半角文字)はきちんと表示されるのに対し、2バイト文字は化けてしまいます。 きちんと表示されるようにするにはどうすれば良いでしょうか? 開発環境:Visual Studio 2005 C++ 開発言語:C/C++(Win32API)+DirectX9.0b ご存知の方がいましたら、よろしくお願いします。

noname#75566
noname#75566

質問者が選んだベストアンサー

  • ベストアンサー
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.3

#1さんの回答について、念のため少し指摘しておくと... fgetws関数は、「UNICODE 文字列のファイルから UNICODE の文字列を読み込むだけ」という代物ではありません。読み込み対象となるファイルは、あくまでも多バイト文字の並びが格納されていることを想定しています。そして、読み込み際に、setlocale関数で設定されたロケールに基づいて、ワイド文字列への変換が行われます。

その他の回答 (6)

  • MrBan
  • ベストアンサー率53% (331/615)
回答No.7

ISO/IEC9899では、fgetws自体にbinary streamに対する特別な規定はありません。 また、textであろうがbinaryであろうが、基本的にファイルはマルチバイトを仮定してます。 [Although both text and binary wide-oriented streams are conceptually sequences of wide characters, the external file associated with a wide-oriented stream is a sequence of multibyte characters, ...] また。文字(列)入出力関数では以下の変換を規定してます。 [The wide character input functions read multibyte characters from the stream and convert them to wide characters as if they were read by successive calls to the fgetwc function.] # the streamはwide-oriented streamにかかります。 標準仕様は、MBSの読み出しに変換を要求してますが、 「UNICODEが読めてはいけない」規定はありませんので、 MSの実装がこのような仕様でもアリな気がしますが、 すべての処理系がこのような動作をする保証はないかと思います。 # 「バイナリの入出力は一切無変換」の処理系だと、このような動作をする気はしますが、 # 少なくとも、私はこの実装を強制する規定は見つけてません。 # 「fgetwsが常にマルチバイトを仮定して変換を試みる(そしておそらく失敗する)」処理系があってもよさそうに思います。

noname#75566
質問者

お礼

一日で7件もの回答、ありがとうございました。 誠に失礼ながら、皆さんのお礼をまとめてさせていただきたいと思います。 結局、_tsetlocale(LC_CTYPE,TEXT(""));を_fgetts関数の前に挿入することで解決しました。 以前はfgets関数を使用していたのでロケールという概念について無知だったためのミスでした。 おかげさまで上手く動きました。 C#はデフォルトでUNICODEなのに対し、C/C++は後にUNICODEに対応したものですから、VisualStudioの仕様もなかなか難しいですね。 もう少し詳しく勉強したいと思います。 ありがとうございました。

  • noocyte
  • ベストアンサー率58% (171/291)
回答No.6

Microsoft の fgetws() のマニュアルには,入力ストリームが ・テキストモードの場合:マルチバイト文字列を読み出し,(ロケールに従って) ワイド文字列に変換する. ・バイナリモードの場合:Unicode 文字列を読み出す.変換は行われない. と書かれていますが,後者は MS の独自仕様なんでしょうか? テキスト モードとバイナリ モードの Unicode(TM) ストリーム入出力 http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/vclib/html/_crt_unicode.99_.stream_i.2f.o_in_text_and_binary_modes.asp

  • MrBan
  • ベストアンサー率53% (331/615)
回答No.5

既にかかれてますが、fgetwsは 「あくまでも多バイト文字の並びが格納されていることを想定しています。<中略>ワイド文字列への変換が行われます。」 平たく言うと、「マルチバイト文字列のファイル(WindowsならShift-JISが普通。Linuxだと物によりEUCやUTF-8あたり)で書かれたファイルを、 ワイド文字(大抵はUNICODE)の文字列に変換して読み出す」ものなので、 「UNICODEのファイルを読んでも巧く動きません」。 自分で変換がいるのは、むしろファイルがUNICODE等の時です。 # ちなみに、ワイド文字の出力も、読み出し同様にロケールに従った変換が行われます。(ファイルはワイド文字になりません)

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.4

★jacta さんへ ・ロケールの設定をすると『fgetws』関数でも文字列の変換が行われるんですか。 ・お勉強になりました。 ★ketaki さんへ ・というわけで私が紹介した『MultiByteToWideChar』関数を使うよりも『setlocale』関数で  文字列を『fgetws』関数で読み込んだ方が簡単のようです。 ・以上。おわり。

参考URL:
http://www.bohyoh.com/CandCPP/C/Library/setlocale.html
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.2

ロケールの設定は正しく行っていますか?

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.1

★ANSI文字コードのファイルを fgets 関数で読み込む。 ・もともと『ANSI文字コード?』→『シフトJISコード』で書かれたファイルならば  『fgets』関数で一旦読み込んでから、UNICODE 文字列に変換する処理をした後に  DrawTextW メソッドで描画しないと文字化けするのは当然だと思います。 ・私は『fgetws』関数は使ったことはありませんが、この関数は UNICODE 文字列の  ファイルから UNICODE の文字列を読み込むだけですから文字コードの変換は質問者  さんがご自分で行って下さい。 アルゴリズム: (1)『シフトJISコード』で書かれたファイルを『fgets』関数で読み込む (2)読み込んだ文字列を UNICODE 文字列に変換する (3)変換した文字列を ID3DXFont::DrawTextW メソッドなどで描画する 最後に: ・『MultiByteToWideChar』関数は、ANSI 文字列などから Unicode 文字列に変換 ・『WideCharToMultiByte』関数は、Unicode 文字列から ANSI 文字列などに変換 ・以上。おわり。

関連するQ&A

  • UNICODE文字が書き込めるWriteprivateProfileStringのようなファイルに書き込む関数はないですか?

    お世話になります。 VC++ MFC VisaualStidio 2003 で開発しております。 UNICODE文字が書き込めるWriteprivateProfileStringのようなファイルに書き込む関数はないでしょうか? ファイルを使用して、他EXEとやり取りしているのですが、WriteprivateProfileStringは、ANSI文字にもある文字しか使用できないみたいです。 「森鷗外𠮟る」などのUNICODEにしかない文字をファイルを経由して他EXEに渡したいのです。 よろしくお願いします。

  • この文字コードは?

    大変お恥ずかしいレベルの質問です C#で印刷プログラムを作成しました プリンタ出口(注)で待ち構えて出力ログを取ったところ 半角文字の A ⇒ 0024 半角文字の J ⇒ 002D 半角文字の 1 ⇒ 0014 半角文字の 9 ⇒ 001C 全角文字の 印 ⇒ 0F33 全角文字の 験 ⇒ 3982 全角文字の に ⇒ 50D1 全角文字の る ⇒ 50F1 となって出力されています UNICODEやANSIであれば A は 0041 となると思いますが 0024 なのです これは如何なる種類の文字コードなのでしょうか? C#ですから当然UNICODEコードが使われていると思ったのですが・・・・・ 色々調べましたが分かりません 宜しくご指導お願い申し上げます (注)実際の印刷出力では ExtTextOutW API でプリンタに渡しています そこでこの ExteTextOutW API にフックを仕掛けてパラメータをダンプしたのです

  • unicodeと2バイト文字

    文字コードにすごいうとい者なのですが、見慣れない _tmain なんていうものを見てしまって、少し調べてみました。 そうすると、なんだか2バイトでは世界中の文字はもとより、感じすらすべて表すことは不可能で、今のunicode主流は3バイトで表現するのだとか。 で、私の知識の中では、C言語ではwchar_tでunicodeを表現しているらしいのですが、それじゃあ足りないわけで、ちゃんとした3バイト文字を表現するための公式的?な記述方法は(WIN32 APIで)あるのでしょうか。(その他MFCなどでもあれば。) 本人こういう事柄について、今まで考えたこともなく、よくわからないまま質問しているので、どうぞ怒らないでください。 よろしくおねがいします。

  • D3DXCreateFontとID3DXFont::DrawTextによる文字列の縦書き描画

    お世話になっています。 D3DXCreateFontとID3DXFont::DrawTextによって文字列を左上(0,0)右下(20,100)の四角形内に縦書き描画しようと、以下のようにコードを書きました。 CreateFontの第3引数cEscapementを2700にし、 CreateFontの第4引数cOrientationも2700にしてCreateFont、D3DXCreateFontによって作成したフォントで、 SetRect(0,0,20,100); DrawText(Str,-1,&rc,DT_SINGLELINE | DT_WORD_ELLIPSIS | DT_NOCLIP, D3DCOLOR_XRGB(0,0,0)); 上のようにして実行すると、何も表示されません。 SetRectの引数を変えてみたりはしたのですが、それでもやはり上手くいきませんでした。 もちろん、フォントは縦書きフォントを指定しています。 さっぱり原因がわからないので、どなたがご存知の方がいらっしゃれば、ご教授よろしくお願いします。 開発環境:Visual Studio 2005 C++ 開発言語:C/C++(Win32API)+DirectX9.0b

  • [VBS] Unicodeの文字化けを防ぎたい

    VBSでフォルダの操作を行っています。 フォルダ名にUnicodeが含まれる場合エラーが発生します。 なんとか文字列を表示する事が出来ますでしょうか? 【文字化けサンプル.vbs】 ---------------------- REM Unicode(U+2776) str = "❶" REM 表示 msgbox str ---------------------- よろしくお願いします。

  • Unicodeは使うべきなのでしょうか?

    ※いまいち文字コードの事が良くわかっていない者です。 今まで、半角1バイト 全角2バイトでプログラミングして来ました。 しかし最近Unicodeの存在に興味や疑問や怖さが募っています。 ■質問1 ・半角1バイト 全角2バイトという扱いは  将来的に廃止され締め出されてしまう危険などが有るのでしょうか? ■質問2 ・ブラウザ/一部チャットのように多言語同時表示は  文字数分大量の無駄なデータ送信負荷になってないのでしょうか?  時に1文字6バイトにすらなるとも聞くだけに疑問です。 ■質問3 ・Unicodeだと、半角1バイト 全角2バイトの扱いに比べ  保存も管理も通信も、無駄が増えるだけにも思えてしますます。  Unicodeをプログラマーの皆さんはどう認識し使ったり使い分け  しているのでしょうか? 漠然とした質問で申し訳ないですが、 何かご助言を頂けますと幸いです。

  • Vbscript Unicode文字の判定

    今、テキストファイルがあり、その中には「Unicode文字」が含まれています。 タックシール(ダイレクトメール用)に出力するのに、マンション名やビル名は改行しなければなりません。 1行に印字できる文字数は全角で20文字(40バイト)です。 したがって、「住所1」と「住所2(マンションやビル名)」の正確なバイト数を調べるのですが、今、「Unicode」のテキストファイルを作って、確かめたところ、半角文字は、そのまま「Asc()」で正の整数で返ってきます。 また、通常の2バイト文字(全角スペースから外字の最終文字)までは、負の整数で返ってきました。 しかし、「Unicode」文字は、常に「63」で返ってきます。 Character Code「63」は、半角の「?」です。 どうやら、「VBScript」は「Unicode」文字をすべて「?」として認識してしまうようです。 通常は、住所に「?」はないはずなのですが、最近、お客様のデータを見ていると、半角の「-」が、よく、半角の「?」に化けているので、「?」はちゃんと1バイトとして、Unicodeの文字は2バイトとして調べなければなりません。 VBAのように「Len()」と「LenB()」があれば、問題ないのですが、「VBScript」では、正しく動作しません(すべて「2」と返してきます)。 正確に文字数(バイト数)を調べるには、どうすればよいのでしょうか?

  • ユニークな文字列を作りたい。

    C♯、.NET FrameWordk2.0環境です。 戻り値として32~35桁のユニークな文字列(半角英数字のみ)を返すメソッドを 作りたいと思っています。 GUIDを発行してやれば良いかと思ったんですが、ハイフンが入っていたり、 アルファベットが大文字小文字混じっていたり(小文字のみにしたい)で、そのままでは 使えません。 発行したGUIDを、サクッと半角英数字(英字は小文字に置換)できるような方法は ないでしょうか? または、もっと簡単にユニークな文字列を発行できる方法がありましたら、ご教授 いただけるとありがたいです。 宜しくお願いします。

  • コンソールにUNICODE (C#)

    Console.WriteがUNICODEを出力してくれません。 Console.Write("(UNICODEを含んだ文字列)"); としてもUNICODE依存の文字は全部?になってしまいます。 Windows2000、XPのコンソールにはIMEやクリップボードからUNICODEが入力できるのは確認できているし、CからAPIのWriteConsoleWを使った場合でもUNICODEが出力できることは確認しています。

  • 文字列から1文字取り出すには?

    XP。studio.netです。 文字列から1文字ずつ取り出したいのですがどうしたらいいのでしょうか。 今 「テストは90点だった。」 「helloと言ってました。」 と言うような1バイト文字と2バイト文字が混合した文字列があるとします。 このような文字列から1文字ずつ文字を取り出すにはどうしたらいいでしょうか。 やりたいことは文字列の文章を一瞬で表示するのではなく、 タタタタと0.01秒に1文字ずつ表示するような表示の仕方がやりたいのです。

専門家に質問してみよう