unicodeでテキスト出力するには?

解決


ばとー  2005-11-03 04:23:05  No: 59445

PC[WindowsXP]
モバイル[WindowsCE3.0]
Embedde Visual C++ 3.0 で開発しているのですが、
テキスト出力した時、文字コードが[SHIFT-JIS]でかかれるのですが、
[UNICODE]で出力したい時は、どうすればいいんでしょうか?

FILE *Fkanri;
Fkanri = _wfopen("\\TMEP\\data\fkanri.txt",L"w+t");
obuf_t = _T("test") + _T("\n");
fwprintf(Fkanri,buf_t);

と言う感じです。
よろしくお願いします。


επιστημη  2005-11-03 07:52:15  No: 59446

wchar_t の配列をバイナリで書き込めばいいのとちゃいますやろか。


シャノン  2005-11-03 13:27:40  No: 59447

Unicode とは UTF-16 のことでしょうか。
eVC++ ならば、おそらく wchar_t = UTF-16 だと思われるので、それでいいと思います。
UTF-8 とかだと、WideCharToMultiByte で変換しなければならないのですが…WinCE では、この関数で UTF-8 に変換することはできないみたいですね。

それと、場合によってはBOMを書き込んでおく必要があるかもしれません。


ばとー  2005-11-05 01:24:08  No: 59448

みなさん、ありがとうございます。
C/VC++の基礎が無く。もともとあったサンプルのプログラムを使い、
なんとかやっている状況です。基礎からやり直せ!!と怒られそうですが、
よろしくお願いします。

Unicode は UTF-16のことです。

obuf_t は CString なんですが、
wchar_t の配列を書き込見たい時は、
obuf_t から1文字ずつとりだして、配列の中に入れていく感じになるんでしょうか?

CString obuf_t;
wchar_t obuf2_t[5];

obuf_t = _T("test");
for(i = 0, i < 5, i++){
  obuf2_t[i] = obuf_t.Mid(i + 1,1);
}

FILE *Fkanri;
Fkanri = _wfopen("\\TMEP\\data\fkanri.txt",L"wb");
fwprintf(Fkanri,obuf2_t);

こんな感じにしてみましたが、上手くいきません。
すみませんが、よろしくお願いします。


Blue  2005-11-05 01:33:38  No: 59449

S-JIS文字列→Unicode文字列に変換するための関数
mbstowcs
があるので、MSDNで調べてみてはどうでしょうか?
サンプルコードも載っています。


PATIO  2005-11-05 02:23:45  No: 59450

まず、WindowsCEは文字コードは全てUNICODEで扱いますので、

Fkanri = _wfopen("\\TMEP\\data\fkanri.txt",L"wb");
ではなくて
Fkanri = _wfopen(L"\\TMEP\\data\fkanri.txt",L"wb");
または、
Fkanri = _wfopen(_T("\\TMEP\\data\fkanri.txt"),_T("wb"));
としないと駄目です。
あと、つかうなら_T()にするのか、L""にするのか統一した方が良いです。
単に混乱を招くだけになります。

_T("a")がL"a"と同じになるのは_UNICODEが定義されている時です。
これはeVCでも同じだったと思います。

CStringは_UNICODEが定義されていると内部処理がUNICODE用になるはずなので
もしCStringに放り込むとSJISになると言うのであれば、_UNICODEが付いていないのかもしれません。
eVCを使っていたのがずいぶん前なので記憶が怪しいですけれど。

あと、WindowsCEだとWindowsのサブセットと言う扱いなので
Windowsだと出来る事がCEでは出来ないなんて事は当たり前にありますので
注意してください。
それこそ例を挙げきれないほどの話なのでどんなのがあるかと言う突っ込みは不許可です。
自分が使う機能についてその都度確認するようにしてください。
この手の確認は通常はMSDNを使ってします。


Blue  2005-11-05 02:31:14  No: 59451

> まず、WindowsCEは文字コードは全てUNICODEで扱いますので、
そうでした。。。

ということは、
いちいちwchar_t型に入れなくても、書き込めるはずですね。

> Fkanri = _wfopen(_T("\\TMEP\\data\fkanri.txt"),_T("wb"));
でしたら、
_tfopen等のTCHARルーチンを使うべきですね。


ばとー  2005-11-06 04:02:04  No: 59452

ありがとうございます。

Fkanri = _wfopen(L"\\TMEP\\data\fkanri.txt",L"wb");
だとコンパイルで、エラーは出ないんですが、

Fkanri = _wfopen(_T("\\TMEP\\data\fkanri.txt"),_T("wb"));
だとコンパイルで、エラーがでます。

ということは、UNICODEの定義が出来ていないということでしょうか?

定義というのは、[プロジェクト(P)−設定(S)]で C/C++タブ内のカテゴリ:
全般にあるプリプロセッサの定義に、
UNICODE,_UNICODEを追加しているのですが、
これではだめと言うことでしょうか?


PATIO  2005-11-07 20:31:59  No: 59453

プロジェクトの設定には、ReleaseとDebugがありますが、
実際にビルドに使っている方の設定を変更していますか?
というか、WindowsCE用のプロジェクトであれば、最初から設定済みのはずだと
思うのですけれど。
あと、状況の判断をしてもらいたいのであれば、
エラーの内容まで載せないと駄目ですよ。
エラーメッセージをそのままコピペした方が間違いないです。
どうしてもわからないのであれば、プロジェクトから作り直した方がいいかも
しれません。


ばとー  2005-11-07 21:09:36  No: 59454

ありがとうございます。

>あと、状況の判断をしてもらいたいのであれば、
>エラーの内容まで載せないと駄目ですよ。
すみません。全くその通りです。

Fkanri = _wfopen(_T("\\TMEP\\data\fkanri.txt"),_T("wb"));
[_T]にした時の、エラー内容です。
D:\開発\塩干\BT2000\Test\TestDlg.cpp(918) : error C2065: '_T' : undeclared identifier
D:\開発\塩干\BT2000\Test\TestDlg.cpp(918) : error C2143: syntax error : missing ')' before 'string'
D:\開発\塩干\BT2000\Test\TestDlg.cpp(918) : error C2059: syntax error : ')'

>実際にビルドに使っている方の設定を変更していますか?
プロジェクトの設定->設定の対象の
[Win32 (WCE ARM) Debug][Win32 (WCE ARM) Release]・・・等いろいろいとありますが、
すべてに、UNICODE/_UNICODEはありました。
実際のビルドは、バッチビルドで[Debug][Release]両方しています。
実行しているのは、[Releas]の方です。

何度もすみませんが、よろしくお願いします。


RAPT  2005-11-07 22:21:13  No: 59455

_Tマクロが未定義といっているだけですよね。
_Tマクロを使用するには、TCHAR.Hが必要です。

_Tマクロに関しては、MSDNで「汎用テキスト マッピングの使用」の項を
参照すると良いと思います。

すでに他の方からの指摘があるように。CE専用なら、
  _wfopen(L"\\TMEP\\data\\fkanri.txt", L"wb");
を使うか、汎用性を気にして
  _tfopen(_T("\\TMEP\\data\\fkanri.txt"), _T("wb"));
とするかです。

ところで、ファイル名でfkanriのところが \\fkanri ではなく
\fkanri なのは只のtypoでしょうか?  それとも意図して?


Blue  2005-11-07 22:28:36  No: 59456

> TCHAR.H
あれ?CStringでつかっているから定義されているはずなんですけどね?

> _tfopen
もうどうせならば、CFileかCStdioFileにしてしまったほうがよさげ。


PATIO  2005-11-07 23:37:29  No: 59457

>> _tfopen
>もうどうせならば、CFileかCStdioFileにしてしまったほうがよさげ。

この意見に一票。
_tfopenを使うことに特別な意味が無いのであれば、MFCを使うようにして
_UNIOCDEで全て制御した方が楽です。
只、_UNICODEが利いていない様なのが気になるところ。
あまり挙動がおかしいようならプロジェクトから作り直して
コードの部分だけコピペした方がいいかもしれません。
プロジェクトファイルの設定がおかしくなっているのかもしれないし。


ばとー  2005-11-08 18:06:30  No: 59458

みなさんありがとうございます。

RAPTさん
>ところで、ファイル名でfkanriのところが \\fkanri ではなく
>\fkanri なのは只のtypoでしょうか?  それとも意図して?
只のtypoでした・・・

Blueさん、PATIOさん
CStdioFileでやってみました。

CStdioFile fout;
CString fname,obuf_t;
fname = _T("\\メモリ カード\\data\\kanri.txt");

fout.Open(fname,CFile::modeCreate | CFile::modeWrite );
obuf_f = _T("test\n");
fout.WriteString(obuf_t);
fout.close();  

上記のようにやってみましたが、次のようなエラーが出ます。

D:\開発\塩干\BT2000\Test\TestDlg.cpp(944) : error C2039: 'WriteString' : is not a member of 'CStdioFile'
        C:\Windows CE Tools\WCE300\BT2000\Mfc\Include\afx.h(1489) : see declaration of 'CStdioFile'
D:\開発\塩干\BT2000\Test\TestDlg.cpp(945) : error C2039: 'close' : is not a member of 'CStdioFile'
        C:\Windows CE Tools\WCE300\BT2000\Mfc\Include\afx.h(1489) : see declaration of 'CStdioFile'

WriteStringはつかえない?
いろいろとみていたら、CEではCStdioFile::WriteStringはありませんという
記述をネットで見たのですが、どうなんでしょうか?


επιστημη  2005-11-08 18:28:19  No: 59459

> いろいろとみていたら、CEではCStdioFile::WriteStringはありませんという
> 記述をネットで見たのですが、どうなんでしょうか?

メソッドが有るか無いかなんて、ヘッダ見れば一発でわかるやん。
訊くまでもないでしょ。


Blue  2005-11-08 18:34:17  No: 59460

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcemfc/htm/cstdfile.asp
ホンマですね。

では CFile の Write メソッドで書き込むのかなぁ。

fout.Write( obuf_t, sizeof( TCHAR ) * obuf_t.GetLength() );


PATIO  2005-11-08 18:39:45  No: 59461

調べなおしてみたら、メソッドが全滅ですね。
コンストラクタはあるくせに。

CFileで実装するしかなさそうです。
CEのファイルシステムの実装は通常のWindowsとは違うので
CStdioFileそのものに意味が無いのかもしれません。


ばとー  2005-11-10 02:52:57  No: 59462

みなさんありがとうございます。
アドバイスを参考に、次のようにつくってみました。(無理矢理な感じがしますが)

CFile fout;
CFileException err;
fout.Open(L"\\メモリ カード\\data\\kanri.txt", CFile::modeCreate | CFile::modeWrite , &err);

wchar_t wBom = 0xfffe;
fout.SeekToEnd();
fout.Write(&wBom,sizeof(wBom));

obuf_t = _T("test\r\n");
wchar_t *p = new wchar_t[obuf_t.GetLength()+1];
wcscpy( p, obuf_t );
fout.SeekToEnd();
fout.Write(p, sizeof(wchar_t) * wcslen(p));
fout.Close();       
delete [] p;

BOMを書き込んだのですが、テキストファイルをバイナリエディタで見てみました。

0xfffe + "test\r\n" を書き込めば、 
FF FE 74 00 65 00 73 00-74 00 0D 00 0A 00  となると思ったのですが、

実際は
FE FF 74 00 65 00 73 00-74 00 0D 00 0A 00  になってまいす。
^^^^^
最初の2バイトが逆になっているんです。

&#63730;wBom = 0xfffe としているんですが、何かまずいところがあるんてしょうか?
ちなみに、エディタで [FE FF] -> [FF FE] に変更して、
メモ帳(文字コードUNICODE)で開くと、文字化けせずに test と表示されます。

何度もすみません。よろしくお願いします。

&#63731;


ばとー  2005-11-10 02:57:18  No: 59463

すみません。見苦しいところが・・・

>&#63730;wBom = 0xfffe としているんですが、何かまずいところがあるんてしょうか?
これは、
wBom = 0xfffe としているんですが、何かまずいところがあるんてしょうか?

なにか変な文字を入れたんでしょうか?


isshi  2005-11-10 05:44:13  No: 59464

>wBom = 0xfffe としているんですが、何かまずいところがあるんてしょうか?
wBom = 0xfeff; では?

参考
http://e-words.jp/w/BOM.html


ばとー  2005-11-10 07:41:22  No: 59465

ありがとうございます。

WindowsでのUnicodeテキストは,リトルエンディアンのUTF-16かと思っていたのですが、(標準というか、なんというか)
リトルエンディアン 0xfffe
ピックエンディアン 0xfeff
違いましたっけ!うーむ?勘違い?

あと、0xfffe で書き込んでいるつもりなのですが、
実際 0xfeff になっているところがよくわかりません。


YuO  2005-11-10 11:28:15  No: 59466

BOMはBE/LEのどちらにおいてもU+FEFFです。
# U+FFFEは使用禁止。

この値を,バイトストリームに転写するとき,
・ビッグエンディアンの環境ではFE FF
・リトルエンディアンの環境ではFF FE
と出力されます。


ばとー  2005-11-12 19:30:55  No: 59467

みなさんありがとうございます。

>この値を,バイトストリームに転写するとき,
>・ビッグエンディアンの環境ではFE FF
>・リトルエンディアンの環境ではFF FE
>と出力されます。
そうだったんですね、U+FEFFで出力したら、FF FEになっていました。
勉強不足でした。

みなさんのおかげで何とかできました。
すごく勉強になりました。
感謝感謝です。
ありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加