GB(中国語)で作成したファイルを読み込み、UTF-8に変換するプログラムを
作成しています。
読み込むファイルの内容は「你你」が入っています。
下記プログラムを実行すると、ctestbuffには下記で設定されます。
EF BE 84 E7 BF 94 E3 83 BB 00
このファイルをひでまるでUTF-8で保存すると下記で設定されます。
E4 BD A0 E4 BD A0 0D 0A,
想定では同値となるはずなのですが、どこか設定が悪いのでしょうか。
尚、中国語なので、初めにsetlocale(LC_ALL, chinese);としています。
環境VC2003
WindowsXP(日本語OS) 日本語OSがまずいのでしょうか?
void Test2(){
char ctestbuff[256];
CStringA cRet;
CStringA cReadTestA;
CStringW cReadTestW;
setlocale(LC_ALL, zh);
// ICONT別IO情報CSVファイルオープン
FILE *fpp = fopen( D:\\temp\\gb.txt, r );
if( fpp == NULL ){
return ;
}
while(1){
// HIM用IO情報CSVデータを1行読み取り
fgets( ctestbuff, sizeof( ctestbuff ), fpp );
if( feof( fpp ) ){
break;
}
cReadTestA = ctestbuff;
cReadTestW = cReadTestA;
cRet = UTF16toUTF8(cReadTestW);
strcpy(ctestbuff,cRet);
}
fclose(fpp);
}
CStringA UTF16toUTF8(const CStringW& utf16)
{
CStringA utf8;
int len = WideCharToMultiByte(CP_UTF8, 0, utf16, -1, NULL, 0, 0, 0);
if (len>1)
{
char *ptr = utf8.GetBuffer(len-1);
if (ptr) WideCharToMultiByte(CP_UTF8, 0, utf16, -1, ptr, len, 0, 0);
utf8.ReleaseBuffer();
}
return utf8;
}
CStringAとCStringWの変換規則って定義されていましたっけ。
コードを流し読みした限りだと,あくまでCP_THREAD_ACPを使ってAPIによる変換をしてい
るようにしか見えませんが。
つまり,setlocaleは全くの無駄のようです。
・fgetsをfgetwsに変更して,ワイド文字列を読み込む
・fgetsで取得した文字列を,該当コードページ (936?) を使って,MutliByteToWideChar
を自分で発行する
といった方法を試してみてはどうでしょうか。
YuOさん回答ありがとうございます。
CStringAとCStringWに関してはMFCが自動で変換してくれるようです。
(SHIFTJISとUNICODEではうまくいっていますが、これに関しては使用しなくてもかまい
ません。)
fgetwsに関しては、処理自体は既存の処理に手を加えるので、fgetsを使用する必要があ
ります。
fgetsでバイトコードは「C4,E3,C4,E3」と正しく読めているので、
これを画面上に「你你」と表示する方法はあるのでしょうか?
上記はUTF-8で設定後、そのデータを画面上に表示するのが目的です、そもそもGBのデー
タを画面上に表示できるかを確認しようとしています。
ファイルから読み込んだ文字「にーはおの1つ目の文字を2つ入れてます」をSIMHEIフ
ォントにしたダイアログへの表示はうまくいきました。
やはりWideCharToMultiByte関数のUTF-8への変換がうまくいかないみたいです。
単純にGBコードの文字を表示したいだけなら
GBに対応したフォントを使って文字を描画すれば良いだけではないかと
思います。読み込めたコードが正しいかを見たいだけならと言う話です。
エディットボックスやスタティックコントロールなら対応するフォントを
コントロールに設定して文字列を設定すれば良いような気がします。
それともやりたい事がこれとは違う事なんでしょうか。
あらら、入れ違いになってしまった。
そもそもCStringで変換しているGBからunicodeへの変換は
うまくいっているのでしょうか?
そこの確認をしないとWideCharToMultiByteでの変換の話は
出来ないと思いますけれど。
> cReadTestA = ctestbuff;
> cReadTestW = cReadTestA;
この処理は何のために入れてるんですか?
UTF16toUTF8 に直接 ctestbuff を渡せばいいような気がするんですが。
あ、ごめん。勘違い。元が UTF-16 じゃないのか。
なら、CString を使わず、MultiByteToWideChar で UTF-16 にすべきだと思います。
MultiByteToWideChar及びWideCharToMultiByteで再度確認しましたが、
結果は変わりませんでした。
実行環境は、「マルチバイト文字セットを使用する」で実行しています。
又、setlocaleは必要なのでしょうか?とりあえず中国で設定しています。
char ctestbuff[8];
char cBuffUtf8[16];
wchar_t cBuffUtf16[16];
setlocale(LC_ALL, zh-cn); // これは必要でしょうか?
// ICONT別IO情報CSVファイルオープン
FILE *fpp = fopen( D:\\temp\\gb.txt, r );
if( fpp == NULL ){
return ;
}
while(1){
fgets( ctestbuff, sizeof( ctestbuff ), fpp );
if( feof( fpp ) ){
break;
}
//画面上に文字を表示 期待通りの文字が出力される
//取得文字:C4 E3 0A (にーはおのにーの一文字)
m_EdTest1.SetWindowText(ctestbuff);
//UTF-16変換
::MultiByteToWideChar(CP_ACP, 0, ctestbuff,strlen(ctestbuff),
cBuffUtf16,sizeof(cBuffUtf16));
//UTF-8変換
WideCharToMultiByte(CP_UTF8, 0, cBuffUtf16, -1, cBuffUtf8,
sizeof(cBuffUtf8), 0, 0);
//UTF-16変換
::MultiByteToWideChar(CP_UTF8, 0, cBuffUtf8,strlen(cBuffUtf8),
BuffUtf16,sizeof(cBuffUtf16));
//変換
WideCharToMultiByte(CP_ACP, 0, cBuffUtf16, -1, ctestbuff,
sizeof(ctestbuff), 0, 0);
//画面上に文字を表示 文字化け!!
m_Ed2.SetWindowText(ctestbuff);
}
fclose(fpp);
元はやっぱりUTF-16っぽいよ。
これなら意味わかりますか?
WCHAR wstr[] = {20320, 20320, 0};
cReadTestW = wstr;
cRet = UTF16toUTF8(cReadTestW);
strcpy(ctestbuff,cRet);
>fgetsでバイトコードは「C4,E3,C4,E3」と正しく読めているので、
あ、元はこっちか。
ごめん。勘違いorz
> //UTF-16変換
> ::MultiByteToWideChar(CP_ACP, 0, ctestbuff,strlen(ctestbuff),
> cBuffUtf16,sizeof(cBuffUtf16));
この第一引数は 936 でしょう。
で、それはそれとして、そもそも、UTF-8 を直接表示したいのはどうしてですか?
UTF-16 に変換して表示するのでは、何か都合が悪いのですか?
UTF-16 で表示するのなら、適切なフォントを選んだ上で TextOutW なり何なりすればい
いのですが、UTF-8 の直接表示は方法がわかりません。
> ごめん。勘違いorz
うん、俺も同じ勘違いw
作成中のアプリはWindowsでUTF-8としてデータを作成し、LINUXでそのデータを使用しま
す。
ですので、画面上でUTF-16として中国語を扱い、データの保存はUTF-8に変換ということ
を実現したいのです。
日本語と中国語をオプションで切り分けており、日本語はうまくいっているのですが、
中国語は文字化けしてしまう状況です。
えっと、俺また勘違いした?
例えば、TextOut の引数に、UTF-8 でエンコードされた char 配列を渡して表示した
い、ということを意図していますか?