IBM提供の文字コード変換ライブラリです。
主に、XercesでEUC-JPを正しく使うためににも使えます。
IBMのICUのページからICU4Cのicu-x.x.zipをダウンロードします(2006/02/26現在3.4が最新)。
icu-x.x.zipを適当なフォルダに解凍します。解凍して作られたフォルダicuを以後[ICU_FOLDER]と呼びます。
ライブラリのビルドは、[ICU_FOLDER]/source/allinone/allinone.slnファイルをVisualStudioで開きます。このとき、allinone.slnがvc 7.1で作られているため変換しますか?と聞かれるので変換しましょう。
その後、アクティブなターゲットがDebugになっているのを確認して、ソリューションのビルドを行います。次に、アクティブなターゲットをReleaseに変更してソリューションのビルドを行います。
Debug版→Release版の順でビルドを行うのは、出力されるexeが当たり前ですが、Debug版とRelease版で同名なので、exeについてはRelease版を残したいためです。ライブラリについては、Debug版はxxxd.dllとdが付いているため区別され、別ファイルとして保存されます。
ビルドされたライブラリは、[ICU_FOLDER]/libへ出力されます。また、dll、exeは[ICU_FOLDER]/binに出力されます。
ICUを使うには、
shift_jisをUNICODEへ変換するには、こんな感じです。windows向けという事で、shift_jisではなく、windows-31jを指定しています。
#include <string.h>
#include <unicode/ucnv.h>
#include <unicode/uclean.h>
// ライブラリをリンクするためのおまじない
#ifdef _DEBUG
#pragma comment(lib, "icuucd.lib")
#else
#pragma comment(lib, "icuuc.lib")
#endif
int main(int /* argc */, char** /* argv */)
{
const char* const INPUT_STRING="hogeほげ/~";
UErrorCode error = U_ZERO_ERROR;
// 変換器の初期化
UConverter* cnv = ucnv_open("windows-31j", &error);
if(U_FAILURE(error))
{
// ICUのメモリ解放
u_cleanup();
return 1;
}
// 必要なメモリ量を確認
const int32_t unicodeLen
= ucnv_toUChars(cnv, 0, 0
, INPUT_STRING
, strlen(INPUT_STRING)
, &error);
if(0 == unicodeLen)
{
// 変換器解放
ucnv_close(cnv);
// ICUのメモリ解放
u_cleanup();
return 1;
}
error = U_ZERO_ERROR;
UChar* pBuf = new UChar[unicodeLen+1];
ucnv_toUChars(cnv, &pBuf[0], unicodeLen
, INPUT_STRING
, strlen(INPUT_STRING)
, &error);
if(U_FAILURE(error))
{
delete [] pBuf;
// 変換器解放
ucnv_close(cnv);
// ICUのメモリ解放
u_cleanup();
return 1;
}
pBuf[unicodeLen] = L'\0';
// 変換したUNICODE文字で何か処理をする
// 後始末
delete [] pBuf;
// 変換器解放
ucnv_close(cnv);
// ICUのメモリ解放
u_cleanup();
return 0;
}
UNICODEをsjis変換するには、こんな感じです。windows向けという事で、shift_jisではなく、windows-31jを指定しています。
#include <string.h>
#include <unicode/ucnv.h>
#include <unicode/uclean.h>
// ライブラリをリンクするためのおまじない
#ifdef _DEBUG
#pragma comment(lib, "icuucd.lib")
#else
#pragma comment(lib, "icuuc.lib")
#endif
int main(int argc, char** argv)
{
const wchar_t* const INPUT_STRING=L"hogeほげ/~";
UErrorCode error = U_ZERO_ERROR;
// 変換器の初期化
UConverter* cnv = ucnv_open("windows-31j", &error);
if(U_FAILURE(error))
{
// ICUのメモリ解放
u_cleanup();
return 1;
}
// 必要なメモリ量を確認
const int32_t mbsLen
= ucnv_fromUChars(cnv, 0, 0
, INPUT_STRING
, wcslen(INPUT_STRING)
, &error);
if(0 == mbsLen)
{
// 変換器解放
ucnv_close(cnv);
// ICUのメモリ解放
u_cleanup();
return 1;
}
error = U_ZERO_ERROR;
char* pBuf = new char[mbsLen+1];
ucnv_fromUChars(cnv, &pBuf[0], mbsLen
, INPUT_STRING
, wcslen(INPUT_STRING)
, &error);
if(U_FAILURE(error))
{
delete [] pBuf;
// 変換器解放
ucnv_close(cnv);
// ICUのメモリ解放
u_cleanup();
return 1;
}
pBuf[mbsLen] = '\0';
// 変換した文字で何か処理をする
// 後始末
delete [] pBuf;
// 変換器解放
ucnv_close(cnv);
// ICUのメモリ解放
u_cleanup();
return 0;
}
ICUを使って、マルチバイト文字をマルチバイト変換関数を実相してみます。
util.lzhを見て下さい。そのうち、時間を作って説明を書きます。ひとまず、概要だけ。配列のデータ確保後のメモリ解放忘れを避けるため、boostのscoped_arrayを使っています。また、ucnv_openで確保したデータの解放し忘れを避けるため、UConvCloserというデストラクタでucnv_closeを呼び出すクラスを実相してます。