#ifndef SJIS_2_UTF8_H_INC_ #define SJIS_2_UTF8_H_INC_ // Shift-JISからUTF-8へ変換するコード By Sato-Si // オリジナルコード(Perlです) http://www2s.biglobe.ne.jp/~satosi/gmap/suft8.pl //  ※UTF-8からShift-JISへの変換はいずれつける予定(Perlのコードは存在する) // ※実行には以下のファイル(Unicode Consortiumで公開されているMicrosoft CP932の変換表)が必要です。 // ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP932.TXT #include #include #include // 文字列分割用マクロ #define SPLIT_MM_(out1,out2, f, in1) { int pos = in1.find(f); out1 = in1.substr(0,pos); out2 = (pos == string::npos)? "":in1.substr(pos+1); } #define SPLIT_MM_COP_(in1, f) { string tmp; int pos = in1.find(f); in1 = in1.substr(0,pos); } // Shift-JISからUTF-8へ変換するコード By Sato-Si // 戻り値:UTF-8に変換済みの文字列。wstring(UNICODE)じゃないよw // 引数 strはUTF-8に変換したい,Shift-JISコード。これは,書き換えません。 // 引数 need_bomはBOMコードを追加。BOMとはファイルの先頭に書くためのバイトオーダもつけて出す。動作は "\xEF\xBB\xBF" を先頭につけるだけ。必須ではないがこれをつけるファイルは文字化けしにくくなる。 std::string SJis2Utf8(const std::string& str, bool need_bom = false) { using namespace std; string ret; int i; int index; static bool sjs2utf8_x_x_init = false; static map _sjis2utf8_table; // 文字コード変換テーブル Shift-JISコード -> UTF-8文字 // 文字コード変換テーブル設定 開始(最初にこの関数を呼び出した時のみ実行) if(sjs2utf8_x_x_init == false) // 変換テーブル初期化がまだ? { string comment; string sjiscode; string sjiscode_pre; string unicode; string unicode_pre; string zero; string buf; int work; int sjiscodenum; ifstream CP932("CP932.TXT"); // BUG? この関数を呼び出したときに,カレントディレクトリに,CP932.TXTの変換表のファイルがないと,正常動作しません(w; while(CP932 && getline(CP932,buf) ) { SPLIT_MM_COP_(buf, '#') // コメントを切り取る 0x01 0x0001 #START OF HEADING SPLIT_MM_(sjiscode_pre, unicode_pre, '\t', buf) // 2つの数字を分ける 0x01 0x0001 SPLIT_MM_COP_(unicode_pre, '\t') // 後ろにある タブ文字を切り取る(あればですが・・) SPLIT_MM_(zero, sjiscode, 'x', sjiscode_pre) // Shift-JISの方の 0x01 の xで分けることで,0と01に分ける if(!zero.empty() && zero[0] == '0') // 文字列が 0x で始まるときのみ,数値があると認識 { SPLIT_MM_(zero, unicode, 'x', unicode_pre) if(!zero.empty() && zero[0] == '0') { // UNICODEの数値が 0xで始まらない場合(対応するものがない場合)変換表に登録しない sscanf(unicode.c_str(), "%x", &work); sscanf(sjiscode.c_str(), "%x", &sjiscodenum); char tmp[6]; if(work <= 0x7F) { // UTF-8で1バイト文字な時 tmp[0] = work; tmp[1] = '\0'; _sjis2utf8_table[sjiscodenum] = tmp; } else if(work <= 0x7FF) { // UTF-8で2バイト文字な時 tmp[0] = 0xc0|(work >> 6); tmp[1] = 0x80|(work & 0x3f ); tmp[2] = '\0'; _sjis2utf8_table[sjiscodenum] = tmp; } else { // UTF-8で3バイト文字な時 tmp[0] = 0xe0|(work >> 12); tmp[1] = 0x80|((work >> 6) & 0x3f); tmp[2] = 0x80|(work & 0x3f ); tmp[3] = '\0'; _sjis2utf8_table[sjiscodenum] = tmp; } } } } CP932.close(); sjs2utf8_x_x_init = true; // 変換テーブル初期化済みのフラグを立てる } // 文字コード変換テーブル設定 終了 // 変換開始です const unsigned char* strArray = (const unsigned char*)str.c_str(); // 符号無し型を明記しないと,下のif文が上手くいかないなり ret=""; if(need_bom) { //# BOMコードを追加 ret = "\xEF\xBB\xBF"; } for(i = 0; strArray[i] != '\0'; i++) { if((strArray[i] >= 0x80 && strArray[i] < 0xA0) || strArray[i] > 0xDF) { //# 2バイト文字 Shift-JIS半角カナ系の文字をちゃんと対応させる index = ((long)strArray[i]) * 0x100 + ((long)strArray[i+1]); i++; } else { index = strArray[i]; } ret += _sjis2utf8_table[index]; } return ret; } #endif // #ifndef SJIS_2_UTF8_H_INC_