文字列をUTF8からShift-JISに変換する際の「円記号/バックスラッシュ」に対応する[encoding.js]
JavaScriptでencoding.jsを使用して文字列をUnicodeのUTF8からShift-JIS(SJIS)へ変換する際に「円記号」(バックスラッシュ)は「?」に変換されてしまいます。今回はencoding.jsを修正して「円記号」に対応する方法をご紹介します。
UTF8からSJISへ変換する
JavaScriptで文字コードを変換するにはオープンソースの「encoding.js」を利用している方が多いかも知れません。
https://github.com/polygonplanet/encoding.js
ただ、コード変換のテーブルが「べた書き」なのでファイルのサイズが大きいのが難点です。そのうち、軽量版が公開されるかも知れません。
円記号/バックスラッシュ
Windowsや日本語フォントなどでは「バックスラッシュ」の文字コードを「円記号」として表示している場合が多いです。文字コードの詳細は次のようになります。
記号 | Unicode | UTF8 | Shift-JIS(SJIS) | |
---|---|---|---|---|
円記号 | ¥ | U+00A5 | 0xC2A5 | 存在しない |
バックスラッシュ | \ | U+005C | 0x005C | 0x005C |
キーボードで「¥」記号を押すと「0x005C」となります。パソコン黎明期に日本としては「¥」が必要でしたので、半ば強引に「\」を「¥」にしたんでしょうね^^;
本題ですが、この表を見て頂くとお分かりになると思いますが、Unicode/UTF8の「¥」記号をShift-JISに変換する事はできません。何故ならば、「¥」記号の文字コードはShift-JISには存在しないからです。
ですので、「encoding.js」でUTF8の「¥」をSJISへ変換すると「?」になります。
encoding.jsの変更
UTF8からSJISへ変換する際に「¥」を対応させるにはUTF8ToSJIS()の関数を次のように変更します。
function UTF8ToSJIS(data) { var results = []; var i = 0; var len = data && data.length; var b, b1, b2, utf8, jis; for (; i < len; i++) { b = data[i]; if (b >= 0x80) { if (b <= 0xDF) { // 2 bytes. utf8 = (b << 8) + data[++i]; } else { // 3 bytes. utf8 = (b << 16) + (data[++i] << 8) + (data[++i] & 0xFF); } jis = UTF8_TO_JIS_TABLE[utf8]; if (jis === void 0) { // *** 変更の開始 // UTF8の円記号(\)をSJISのバックスラッシュ(表記上は\)に変換 if(utf8 == 0xC2A5){ results[results.length] = 0x5C; }else{ results[results.length] = UTF8_UNKNOWN; } // *** 変更の終了 // 元のコード //results[results.length] = UTF8_UNKNOWN; } else { if (jis < 0xFF) { results[results.length] = jis + 0x80; } else { if (jis > 0x10000) { jis -= 0x10000; } b1 = jis >> 8; b2 = jis & 0xFF; if (b1 & 0x01) { b1 >>= 1; if (b1 < 0x2F) { b1 += 0x71; } else { b1 -= 0x4F; } if (b2 > 0x5F) { b2 += 0x20; } else { b2 += 0x1F; } } else { b1 >>= 1; if (b1 <= 0x2F) { b1 += 0x70; } else { b1 -= 0x50; } b2 += 0x7E; } results[results.length] = b1 & 0xFF; results[results.length] = b2 & 0xFF; } } } else { results[results.length] = data[i] & 0xFF; } } return results; }
変更箇所は23行目から32行目です。UTF8の円記号(¥ - 0xC2A5)をSJISのバックスラッシュ(表記上は¥ - 0x5C)に変換しているだけです。
encoding.jsのソースコードはあんまり読み込んでいないので、もっと良い手法があるかも知れません。
※この記事を作成した時点のencoding.jsのバージョンは「1.0.24」です。