« UnicodeStringをJIS(ISO-2022-JP)に変換すると文字が減る | メイン | Windows XPでWideCharToMultiByte関数を使い、ISO-2022-JPに変換するときの注意点 »

Windows 2000でWideCharToMultiByte関数を使うと、ISO-2022-JPのバイト数を間違う

前回のUnicodeStringをJIS(ISO-2022-JP)に変換すると文字が減るの続き。

UnicodeStringをJISコードに変換すると文字が減るという問題です。

AnsiStringT<50220> jis1 = L"文字コード"; //=> 文字コ

Windows 2000におけるWin32APIのWideCharToMultiByte関数の動作がおかしいようです。
WideCharToMultiByte関数は、ISO-2022-JPに変換したときの正しいバイト数を返しません。

なお、Windows XP以降では問題ありませんでした。

次のソースコードは、ユニコード文字列をJIS(ISO-2022-JP)コードに変換したときのバイト数を取得する処理です。

const int codepage = 50220;
UnicodeString WCharSource = L"abcテスト";
int SrcChars = WCharSource.Length();
int DestBytes = WideCharToMultiByte(codepage, 0, WCharSource.c_str(), SrcChars, NULL, 0, NULL, NULL);

WideCharToMultiByte関数は、変換後の文字列を受け取るために必要なバッファのサイズ(バイト数)を返します。

上のコードでは12バイト必要ですが、この関数は「9」を返します。3バイト足りません。

3バイトというと、エスケープシーケンスが思い当たります。
JISコードではエスケープシーケンスを用いて、文字集合を切り替えます。

エスケープシーケンスの計算が正しいか試してみました。

const int codepage = 50222;
UnicodeString WCharSource = L"abcテストabc";
int SrcChars = WCharSource.Length();
int DestBytes = WideCharToMultiByte(codepage, 0, WCharSource.c_str(), SrcChars, NULL, 0, NULL, NULL);

WideCharToMultiByte関数は「12」を返します。6バイト足りません。

const int codepage = 50220;
UnicodeString WCharSource = L"abcテストabcテスト";
int SrcChars = WCharSource.Length();
int DestBytes = WideCharToMultiByte(codepage, 0, WCharSource.c_str(), SrcChars, NULL, 0, NULL, NULL);

WideCharToMultiByte関数は「18」を返します。9バイト足りません。
やはりエスケープシーケンスが考慮されていないようです。

原因がわかりましたので、対策も簡単です。
Windows2000でISO-2022-JPに変換するときはバッファを多めにとればいいのです。

さて、問題のUnicodeStringからAnsiStringT<50220>への変換ですが、 System.pasの_LStrFromPWCharLen関数かCharFromWChar関数で、 文字のバイト数を取得するときに、 OSがWindows2000かつコードページが50220ならば、 バッファのバイト数を増やして文字を取得し、取得後に不要な部分を切り捨てればいいと思います。
とても汚いコードになりそうです。

調べてみると、同じような問題に遭遇している方がいらっしゃいました。
komatの古往今来: ALM2Thunderbird 1.0の動作OSについて」では、Windows 2000環境で変換に失敗するという問題に遭遇されています。
「Windows API関数のWideCharToMultiByteとMultiByteToWideCharの動作に問題がある」とありますが、おそらく同じ問題でしょう。

トラックバック

このエントリーのトラックバックURL:
http://www.gesource.jp/mt/mt-tb.cgi/1065

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)

About

2009年09月15日 21:07に投稿されたエントリーのページです。

ひとつ前の投稿は「UnicodeStringをJIS(ISO-2022-JP)に変換すると文字が減る」です。

次の投稿は「Windows XPでWideCharToMultiByte関数を使い、ISO-2022-JPに変換するときの注意点」です。

他にも多くのエントリーがあります。メインページアーカイブページも見てください。

Powered by
Movable Type 3.35