Win32/64技術 003 ワイド文字列→マルチバイト文字列変換
概要
ワイド文字のUTF-16から変換してマルチバイトのSJIS(Shift_JIS、Microsoft提唱のコードページcp932とも呼ばれる)やUTF-8に変換する方法です。MultiByteToWideChar関数にあい対する関数WideCharToMultiByteを使います。
wchar_t pwchstr[] = L"Win32/64アプリケーション";
int icharLen = WideCharToMultiByte(932, 0, pwchstr, -1, nullptr, 0, nullptr, nullptr);
char* chstr = new char[icharLen];
WideCharToMultiByte(932, 0, pwchstr, -1, chstr, icharLen, nullptr, nullptr);
標準string型 wstring型を使う場合(推奨)
wchar_t pwchstr[] = L"Win32/64アプリケーション";
std::wstring wstringUTF16str = std::wstring(pwchstr);
int icharLen = WideCharToMultiByte(932, 0, wstringUTF16str.c_str(), -1, nullptr, 0, nullptr, nullptr);
std::string stringSJISstr(icharLen, 0);
WideCharToMultiByte(932, 0, wstringUTF16str.c_str(), -1, stringSJISstr.c_str(), stringSJISstr.size(), nullptr, nullptr);
■WideCharToMultiByte(UINT, DWORD, LPCWCH, int, LPSTR, int, LPCCH, LPBOOL)
第1引数:UINT CodePage
文字コードの変換もできます。この関数では変換先の文字コードを指定します。逆変換では、変換元の文字コードを指定していました。
第2引数:DWORD dwFlags
- WC_COMPOSITECHECK:合成文字を検査するためのフラグです。正準分解形の0x0065(e) 0x0301(´)を検出し、きちんと合成文字のéを得ます。指定しない場合は、0x0065(e)と0x0301(´)を別々の文字として処理します。処理速度を犠牲にするので、そのような文字が含まれない場合は指定する必要はないでしょう。
- WC_DEFAULTCHAR:変換中に、変換できない文字をデフォルトの文字(通常は?が使われます)に置き換えるためのフラグです。変換できない文字は、指定したコードページに存在しない場合などに発生することがあります。
- WC_DISCARDNS:ノンスパース文字(Non-Spacing Character)を無視するためのフラグです。ノンスパース文字は、文字コード内で文字を修飾するために使用される文字で、変換中にこれらを無視することができます。合成文字の後ろの文字を無視して、情報が欠落するように変換されます。例えば、
- é(eと´が組み合わさった合成文字)
- â(aと^が組み合わさった合成文字)
- ñ(nと~が組み合わさった合成文字)
- ç(cと,が組み合わさった合成文字)
- ü(uと¨が組み合わさった合成文字)
- ß(sとβの合成)
- ą(aとoストロークの組み合わせ)
- Ż(Zと点付きコンビニング・フックの組み合わせ)
- Œ(OとE合成)
- ę(eとogonekの組み合わせ)
- Ł(Lとbarの組み合わせ)
- ș(sとcedillaの組み合わせ)
- ș(tとcedillaの組み合わせ)
- ǂ(2つの縦線の組み合わせ)
- Č(Cとhacekの組み合わせ)
- Š(Sとhacekの組み合わせ)
- Ž(Zとhacekの組み合わせ)
- ƒ(fとcrossの組み合わせ)
- ₹(RとIndian Rupeeの組み合わせ)
- ☺(smiley faceアイコン)
とかがあります。
- WC_SEPCHARS:パススルー文字を処理するためのフラグです。パススルー文字は、変換されずにそのまま出力される特定の文字です。このフラグを指定すると、パススルー文字が正しく処理されます。パススルー文字とは制御文字やエスケープシーケンスや特殊文字のことを差します。ANSIエスケープシーケンスの\x1B[31m(テキストの色を赤に変更するエスケープ シーケンス)やVT100エスケープ シーケンス"\x1B[2J"(画面クリア)があります。\u00E9のようなユニコードエスケープシーケンスも該当します。\n、\r、\t、\a(ベル音)、\b(カーソルを前に移動)、\0(ヌル文字)、'、"、\エスケープシーケンス程度ならコードページの変換をしても情報が失われることは少ないので、フラグを指定する必要はありません。
- WC_NO_BEST_FIT_CHARS:このフラグを指定すると、ベストフィット文字が使用されず、文字が失われる可能性があります。ワイド文字のé(U+00E9)を変換する場合、ISO 8859-1(Latin-1)ではベストフィット文字として "é"(0xE9)が使われ、 ISO 8859-5(Cyrillic)の場合、ベストフィット文字として "?"(0x3F)が使用されるかもしれないです。このようなベストフィットを使用しないで文字を喪失する方法を選ぶことができます。
- WC_ERR_INVALID_CHARS フラグを指定すると、変換中に無効な文字が検出された場合にエラーを発生させることができます。UTF-16はUnicodeという広範囲な文字セットですので、より小さな文字セットに変換する場合は存在しない文字コードもあります。その場合処理を止める必要があるなら、このフラグが必要です。
第3引数:LPCWCH lpWideCharStr
第4引数:int cchWideChar
第5引数:LPSTR lpMultiByteStr
第6引数:int cbMultiByte
第7引数:LPCCH lpDefaultChar
変換先の文字が無い時のデフォルト変換文字を指定します。このデフォルト変換文字を使うという場合には第二引数のFlagは0でも大丈夫です。
第8引数:LPBOOL lpUsedDefaultChar