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とキャラクタセットに
関する最低限のこと(言い訳なし!)」として解説してあり、この項目を読むだけでもこの本を買う価値はあると思います。もちろん他の項目もすごくためになります。なかりおすすめ。
実際の変換はコードを見ればわかると思います。エラー処理は省略しています。
- BOOL ConvSJistoUtf8( BYTE* pSource, BYTE* pDist, int* pSize )
- {
- *pSize = 0;
- //ShiftJISからUTF-16へ変換
- const int nSize = ::MultiByteToWideChar( CP_ACP, 0, (LPCSTR)
- pSource, -1, NULL, 0 );
- BYTE* buffUtf16 = new BYTE[ nSize * 2 + 2 ];
- ::MultiByteToWideChar( CP_ACP, 0, (LPCSTR)pSource, -1, (LPWSTR)
- buffUtf16, nSize );
- //UTF-16からShift-JISへ変換
- const int nSizeUtf8 = ::WideCharToMultiByte( CP_UTF8, 0, (LPCWSTR)
- buffUtf16, -1, NULL, 0, NULL, NULL );
- if( !pDist ){
- *pSize = nSizeUtf8;
- delete buffUtf16;
- return TRUE;
- }
- BYTE* buffUtf8 = new BYTE[ nSizeUtf8 * 2 ];
- ZeroMemory( buffUtf8, nSizeUtf8 * 2 );
- ::WideCharToMultiByte( CP_UTF8, 0, (LPCWSTR)buffUtf16, -1, (LPSTR)
- buffUtf8, nSizeUtf8, NULL, NULL );
- *pSize = lstrlen( (char*)buffUtf8 );
- memcpy( pDist, buffUtf8, *pSize );
- delete buffUtf16;
- delete buffUtf8;
- return TRUE;
- }
この関数の使用方法は、まずはじめにpDistにNULLを渡して変換後のサイズを
取得します。変換後のサイズでpDistのメモリを確保したあと、もう一度この関数を呼びます。
次のような感じ。
- int nSize = 0;
- ConvSJisToUtf8( pSource, NULL, &nSize );
- BYTE* pDist = new BYTE[ nSize + 1 ];
- ZeroMemory( pDist, nSize + 1 );
- ConvSJisToUtf8( pSource, pDist, &nSize );
次回はUFT-8をShift-JISに変換する方法です。
今回の逆なだけです。