WindowsプログラマのWebアプリへの挑戦日記。あとパンとか。

C++でShift-JISをUTF-8に変換する

6月 11th, 2008 Posted in C++

Windowsアプリケーションでもネットワークにつながって、サーバアプリケーションと連携することが多くなってきてますねぇ。ネットワークといえば文字コードはUTF-8なイメージがあるワタクシですが、C++ではShift-JISなアプリばっかり作ってきたので、UTF-8に変換するにはどうしたらいいの?ってことでまとめます。

C++でShift-JISをUTF-8に変換するには、

Shift-JIS→UTF-16→UTF-8

の順番で変換する必要があります。

そもそも、UTF-16とUTF-8はどう違うのか。UTF-16は文字に割り当てられる番号(コードポイント)が2バイトで格納されます。一方UTF-8は、0~127のコードポイントは1バイトで格納され、128から上のコードポイントは、2~6バイトで格納されます。0~127のコードポイントでは、ASCIIと同じ文字が定義されているので、英語のテキストを扱うときには、ASCIIとUTF-8でまったく同じになります。

このあたりのことは、「Joel on Software」にわかりやすく解説してあります。

「Joel on Software」には、Unicodeに関する項目を「すべてのソフトウェア
開発者が絶対確実に知っていなければならないUnicodeとキャラクタセットに
関する最低限のこと(言い訳なし!)」として解説してあり、この項目を読むだけでもこの本を買う価値はあると思います。もちろん他の項目もすごくためになります。なかりおすすめ。

実際の変換はコードを見ればわかると思います。エラー処理は省略しています。

  1. BOOL ConvSJistoUtf8( BYTE* pSource, BYTE* pDist, int* pSize )
  2. {
  3.    *pSize = 0;
  4.  
  5.    //ShiftJISからUTF-16へ変換
  6.    const int nSize = ::MultiByteToWideChar( CP_ACP, 0, (LPCSTR)
  7. pSource, -1, NULL, 0 );
  8.  
  9.    BYTE* buffUtf16 = new BYTE[ nSize * 2 + 2 ];
  10.    ::MultiByteToWideChar( CP_ACP, 0, (LPCSTR)pSource, -1, (LPWSTR)
  11. buffUtf16, nSize );
  12.  
  13.    //UTF-16からShift-JISへ変換
  14.    const int nSizeUtf8 = ::WideCharToMultiByte( CP_UTF8, 0, (LPCWSTR)
  15. buffUtf16, -1, NULL, 0, NULL, NULL );
  16.    if( !pDist ){
  17.        *pSize = nSizeUtf8;
  18.        delete buffUtf16;
  19.        return TRUE;
  20.    }
  21.  
  22.    BYTE* buffUtf8 = new BYTE[ nSizeUtf8 * 2 ];
  23.    ZeroMemory( buffUtf8, nSizeUtf8 * 2 );
  24.    ::WideCharToMultiByte( CP_UTF8, 0, (LPCWSTR)buffUtf16, -1, (LPSTR)
  25. buffUtf8, nSizeUtf8, NULL, NULL );
  26.  
  27.    *pSize = lstrlen( (char*)buffUtf8 );
  28.    memcpy( pDist, buffUtf8, *pSize );
  29.  
  30.    delete buffUtf16;
  31.    delete buffUtf8;
  32.  
  33.    return TRUE;
  34. }

この関数の使用方法は、まずはじめにpDistにNULLを渡して変換後のサイズを
取得します。変換後のサイズでpDistのメモリを確保したあと、もう一度この関数を呼びます。

次のような感じ。

  1. int nSize = 0;
  2. ConvSJisToUtf8( pSource, NULL, &nSize );
  3. BYTE* pDist = new BYTE[ nSize + 1 ];
  4. ZeroMemory( pDist, nSize + 1 );
  5. ConvSJisToUtf8( pSource, pDist, &nSize );

次回はUFT-8をShift-JISに変換する方法です。
今回の逆なだけです。

こちらもオススメ!

Trackback URL

Post a Comment