.NETに頼らない文字コード変換
ついでにもうひとつ。.NETに頼らず、native-C/C++の範囲で文字コードを変換する方法です。残念ながらC/C++の標準ライブラリは様々な文字コードに対応した変換機能をサポートしてくれません。native世界での文字コード変換ライブラリで僕が愛用しているのがIBMのOpenSource:ICU(International Components for Unicode)です。ICUを使って上記UnicodeConverterをC++で実装してみました。
/*
* ICU による文字コード変換
*/
#include <unicode/ucnv.h>
#include <string>
class UnicodeConverter {
private:
UErrorCode error_;
UConverter* converter_;
public:
explicit UnicodeConverter(const char* name) {
converter_ = ucnv_open(name,&error_);
}
~UnicodeConverter() {
ucnv_close(converter_);
}
bool ok() const { return U_SUCCESS(error_) != 0; }
std::string fromUnicode(const wchar_t* input, int size);
std::wstring toUnicode(const char* input, int size);
std::string fromUnicode(const std::wstring& input)
{ return fromUnicode(input.data(), input.size()); }
std::wstring toUnicode(const std::string& input)
{ return toUnicode(input.data(), input.size()); }
};
// Unicode -> MBCS
std::string UnicodeConverter::fromUnicode(const wchar_t* input, int size) {
std::string result(ucnv_getMaxCharSize(converter_)*size,'\0');
int len = ucnv_fromUChars(
converter_,
&result[0], result.size(), // 変換先のポインタとサイズ
input, size, // 変換元のポインタをサイズ
&error_
);
result.resize(len);
return result;
}
// MBCS -> Unicode
std::wstring UnicodeConverter::toUnicode(const char* input, int size) {
std::wstring result(size,L'\0');
int len = ucnv_toUChars(
converter_,
&result[0], result.size(), // 変換先のポインタとサイズ
input, size, // 変換元のポインタとサイズ
&error_
);
result.resize(len);
return result;
}
/*
* おためし
*/
#include <iostream>
#include <locale>
using namespace std;
int main() {
wcout.imbue(locale("japanese"));
// "JIS文字列" のJIS(iso-2022-jp)表現↓
string jis = "\x4A\x49\x53\x1B\x24\x42\x4A\x38\x3B\x7A\x4E\x73\x1B\x28\x42";
UnicodeConverter jis_converter("iso-2022-jp");
// JIS → UNICODE
wstring unicode = jis_converter.toUnicode(jis);
wcout << L'[' << unicode << L']' << endl;
// UNICODE → JIS
string result = jis_converter.fromUnicode(unicode);
if ( jis == result ) {
wcout << L"元の文字列と一致しました!" << endl;
}
// UNICODE → SJIS
UnicodeConverter sjis_converter("shift_jis");
result = sjis_converter.fromUnicode(unicode);
cout << '[' << result << ']' << endl;
}
