UTF16->SJIS

解決


per  2006-11-18 22:06:01  No: 63636

UTF16で書かれたXMLファイルをSJISに変換したいのですが、うまくいかないので質問させて頂きます。

char * Utf16toSjis(char * data,int len){
  int res,size
  char * buf;

  //UTF-16からSJISに変換した時の領域取得
  res = WideCharToMultiByte(CP_ACP , 0,(const wchar_t *)data, len, NULL, 0, NULL, NULL);
  if(res==0){
     printf("エラー");
    return 0;
  }

  buf = (char *)malloc(sizeof(char)*res);
  if(buf==NULL){
    printf("メモリ割り当てエラー");
    return 0;
  }
  ZeroMemory(buf,res);

  //UTF-16からSJISに
  size = WideCharToMultiByte(CP_ACP , 0, (const wchar_t *)data, len, buf, res, NULL, NULL);
  if(size==0){
    printf("エラー");
    return 0;
  }
  return buf;
}

このようなコードを書いてみたのですが、SJISに変換されるのですが
ファイルの最後に0が多くついてしまい正しく変換されていません。

WideCharToMultiByteの第三引数で無理やりwchar_tにキャストしてるのが原因かと思い、

  res2=MultiByteToWideChar(CP_ACP, 0, data, len, NULL,0);
  
  data2=(wchar_t *)malloc(sizeof(wchar_t)*res2);
  ZeroMemory(data2,sizeof(wchar_t)*res2);
  
  MultiByteToWideChar(CP_ACP, 0, data, len, data2, res2);

のコードを足して見た結果、SJISに変換されず、UTF16のまま、しかも文字化け。

恐らく使い方を間違ってるのだと思います。
また、MultiByteToWideChar,WideCharToMultiByteともに第四引数に-1を付けると自動でサイズを取得すると書いてあったのですが、
1が返ってきてしまい上手く取得できません。

どなたかUTF16からSJISへの変換の仕方を教えて頂けないでしょうか


Blue  2006-11-18 22:36:10  No: 63637

>buf = (char *)malloc(sizeof(char)*res);
が不味いです。

>//UTF-16からSJISに変換した時の領域取得
で取得できるのは、終端文字を含まない文字数ですので、
終端文字分領域を1多く取らなければなりません。
よって

buf = ( char* )malloc( sizeof( char ) * ( res + 1 ) );
WideCharToMultiByte( CP_ACP , 0, (const wchar_t *)data, len, buf, res, NULL, NULL );
buf[ res ] = '\0';

とすればいけると思います。

ちなみにC++であれば、comdefの_bstr_tクラスやMFCのCStringでも簡単に変換できます。


Blue  2006-11-18 22:41:19  No: 63638

また
>また、MultiByteToWideChar,WideCharToMultiByteともに第四引数に-1を付けると自動でサイズを取得すると書いてあったのですが、
のとおり、-1を指定すればキチンと終端文字含みの領域長が帰ってきますよ。

Sample)
#include <windows.h>
#include <string.h>

int main()
{
    wchar_t ws[] = L"あいうえお";
    char* mbs = NULL;
    int len;

    len = WideCharToMultiByte( CP_ACP, 0, ws, -1, NULL, 0, NULL, NULL );
    mbs = ( char* )malloc( len );
    WideCharToMultiByte( CP_ACP, 0, ws, -1, mbs, len, NULL, NULL );

    return 0;
}


Blue  2006-11-18 22:50:46  No: 63639

もしかして
>char * Utf16toSjis(char * data,int len){
で渡すときに、ちゃんと終端が、L'\0' になっていないのでは?
でなきゃ -1 を指定してもちゃんとした長さは取れません。
(L'\0' = 0x0000 )


per  2006-11-18 23:22:14  No: 63640

Blueさん有難う御座います。

まさにL'\0'が原因でした。それに伴い最終的に思ったとおりの結果が得られました。

これを糧に、これからもっと精進させて頂きます。有難う御座いました。


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

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






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