SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

オープンソースC++用クラスライブラリPOCO活用講座

テキスト処理もPOCOにおまかせ

オープンソースC++用クラスライブラリPOCO活用講座(3)

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

シフトJISとUTF-8の相互変換関数

 日本語を含む文字列をPOCOの関数やクラスに渡す場合は、シフトJISコードのままではなく、あらかじめUTF-8コードに変換しておく必要があります。シフトJISのままにしておくと、前述のような文字化けが発生することがあります。そこで、シフトJISからUTF-8に変換する処理が必要になってくるのですが、ヨーロッパ生まれのPOCOはシフトJISには対応していません。当然、シフトJISとUTF-8を相互変換する関数も用意されていませんので、POCOの関数を利用したシフトJISとUTF-8の相互変換関数を作ってみました(Windows環境のみ)。

 Win32 APIだけでも変換はできるのですが、POCOにはUTF-8コードとUTF-16コードの相互変換用の関数が用意されているので、その関数とWin32 APIを利用しています。シフトJISとUTF-8との変換は、直接変換するのではなく、いったんUTF-16にしてから変換しています。

シフトJISをUTF-8に変換

 まず、シフトJIS→UTF-16→UTF-8の変換です。シフトJIS→UTF-16の変換では、APIをそのまま使っています。

シフトJISをUTF-16に変換
std::wstring ShitJIStoUTF16( const std::string& str )
{
    int len = ::MultiByteToWideChar( CP_ACP, 0, 
                                      str.c_str(), 
                                       -1, NULL, 0 );          // (1)
    if ( len>0 ) { 
        std::vector<wchar_t> utf16( len );                     // (2)
        if ( ::MultiByteToWideChar( CP_ACP, 0, 
                                     str.c_str(), -1, 
                                      &utf16[0], len ) )       // (3)
            return std::wstring( &utf16[0] );
    }
    return NULL;
}

 (1)の行で、APIのMultiByteToWideCharを用いて、strをUTF-16コードに変換するのに必要なバッファのサイズ(ワイド文字数)を求めています。CP_ACPは、日本語WindowsではシフトJISコードを指定していることになります。(2)でワイド文字であるwchar_t型の領域を確保して、(3)で実際に変換しています。

 MultiByteToWideCharの定義は次のようになっています。

MultiByteToWideCharの定義
int MultiByteToWideChar(
                UINT CodePage,         // コードページ
                DWORD dwFlags,         // 文字の種類を指定するフラグ
                LPCSTR lpMultiByteStr, // マップ元文字列のアドレス
                int cchMultiByte,      // マップ元文字列のバイト数
                LPWSTR lpWideCharStr,  // マップ先ワイド文字列を入れる
                                       // バッファのアドレス
                int cchWideChar        // バッファのサイズ
               );

 バッファのサイズを0にして呼び出すと必要なバッファサイズを求めることができます。文字の種類を指定するフラグは特に指定する必要はありません。マップ元文字列のバイト数に-1を指定した場合は、文字列はNULLで終わっていると見なして自動的に長さが計算されます。

 UTF-16→UTF-8の変換にはPOCOのtoUTF8関数を使います。まとめると、シフトJIS→UTF-8の変換ソースは次のようになります。

シフトJISをUTF-8に変換
#include "poco/UnicodeConverter.h"

std::string ShitJIStoUTF8( const std::string& str )
{
    std::string utf8;

    // UTF-16にして、UTF-8に変換
    Poco::UnicodeConverter::toUTF8( ShitJIStoUTF16( str ), utf8 );    
    return utf8;
}

UTF-8をシフトJISに変換

 次に、UTF-8→UTF-16→シフトJISの変換です。UTF-16→シフトJISの変換では、APIをそのまま使っています。

UTF-16をSJISに変換
std::string UTF16toShitJIS( const std::wstring& wstr )
{
    int len = ::WideCharToMultiByte( CP_ACP, 0, 
                                      wstr.c_str(), -1, 
                                       NULL, 0, NULL, NULL );  // (1)
    if ( len>0 ) {
        std::vector<char> sjis( len );                         // (2)
        if ( ::WideCharToMultiByte(                            // (3)
                        CP_ACP, 0, wstr.c_str(), 
                         -1, &sjis[0], len, NULL, NULL ) )
                            return std::string( &sjis[0] );
    }
    return NULL;
}

 (1)の行で、APIのWideCharToMultiByteを用いてwstrをシフトJISコードに変換するために必要なバッファのサイズを求めています。CP_ACPは、日本語WindowsではシフトJISコードを指定していることになります。(2)でchar_t型の領域を確保(終端のNULLも含まれている)して、(3)で実際に変換しています。

 WideCharToMultiByteの定義は次のようになっています。

WideCharToMultiByteの定義
int WideCharToMultiByte(
            UINT CodePage,          // コードページ
            DWORD dwFlags,          // 処理速度とマッピング方法を
                                    //   決定するフラグ
            LPCWSTR lpWideCharStr,  // ワイド文字列のアドレス
            int cchWideChar,        // ワイド文字列の文字数
            LPSTR lpMultiByteStr,   // 新しい文字列を受け取る
                                    //   バッファのアドレス
            int cchMultiByte,       // 新しい文字列を受け取る
                                    //   バッファのサイズ
            LPCSTR lpDefaultChar,   // マップできない文字の
                                    // 既定値のアドレス
            LPBOOL lpUsedDefaultChar  // 既定の文字を使ったときに
                                      //   セットするフラグのアドレス
           );

 バッファのサイズを0にして呼び出すと必要なサイズを求めることができます。ワイド文字列の文字数を-1にすると、文字列はNULLで終わっていると見なして自動的に長さが計算されます。その他は特に指定する必要はありません。

 UTF-8→UTF-16の変換には、POCOのtoUTF16関数を使います。まとめると、UTF-8→シフトJISの変換ソースは次のようになります。

UTF-8をシフトJISに変換
#include "poco/UnicodeConverter.h"

std::string UTF8toShitJIS( const std::string& str )
{
    std::wstring wstr;

    // UTF-8をUTF-16に変換
    Poco::UnicodeConverter::toUTF16( str, wstr );    

    return  UTF16toShitJIS( wstr );        // UTF-16をシフトJISに変換
}

 Win32APIのみを使った場合に比べると、POCOの関数を使っている分だけコード量が少なくなっています。

次のページ
ユーティリティ関数

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
オープンソースC++用クラスライブラリPOCO活用講座連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト 高江 賢(タカエ ケン)

WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/2098 2008/01/29 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング