ICUを使おう

目次

ICUとは

IBM提供の文字コード変換ライブラリです。

主に、XercesでEUC-JPを正しく使うためににも使えます。

インストール for VC 8(VisualStudio 2005)

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を使うには、

sjisをUNICODEへ変換

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へ変換

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;
}

マルチバイト・マルチバイト変換(C++らしい解答)

ICUを使って、マルチバイト文字をマルチバイト変換関数を実相してみます。

util.lzhを見て下さい。そのうち、時間を作って説明を書きます。ひとまず、概要だけ。配列のデータ確保後のメモリ解放忘れを避けるため、boostのscoped_arrayを使っています。また、ucnv_openで確保したデータの解放し忘れを避けるため、UConvCloserというデストラクタでucnv_closeを呼び出すクラスを実相してます。