JavaScript 文字コード変換ライブラリ encoding.js 1.0.12 リリース しました
変換テーブルは MS 基本コードポイント (Unicode) を参照していましたが、 UTF-8 に変換する際に無効なコードポイントになってしまい文字化けが発生していました。
MS 基本コードポイントと IBM 基本コードポイントの差は以下のようになっています。
コードポイント:
encoding.js の場合、MS コードポイントのまま変換しようとしていまい、対応する文字がなく '?' などになってしまっていました。
これは元々直したつもりでいたのですが、 encoding.js 1.0.10 Line 2973 あたりを見てみると以下のようになっていて
今回、IBM 基本コードポイントの差分によって変換してあげることで、ぶじ文字化けが解消されました。
前バージョンまでは、JIS→UTF-8 テーブルと UTF-8→JIS テーブルの 2つを保持していたのですが、
今回、UTF-8→JIS のみを静的に持ち、JIS→UTF-8 変換が必要になった際、動的にもう一つのテーブルを生成するようにしました。
生成されるのは呼ばれた最初の 1回のみです。
その際の速度が気になり、ベンチとってみましたが 約 2~5ms 程度で問題ないと思われます。
ファイルサイズは非minifyで 261KB (min: 219KB) だったのが 152KB (min: 116KB) になり、約60% 減らすことができました。
これは非常に遅く、また in を使うより hasOwnProperty が速く、実行環境にもよりますが
変換速度は、1MB の日本語テキスト (UTF-8) に対して SJIS に文字コード変換した場合、平均 約 50ms. (EUC-JP, JIS 等も同程度)、
UNICODE (UTF-16) から UTF-8 とその逆は約 5ms ほどで、前よりだいぶ速くなりました。
文字化けという大きなバグを修正しているので、アップデートをおすすめします。
Node.js では、encoding-japanese というモジュール名になっています
上のようにして利用できます。
encoding.convert() は Buffer に対しても使えます(配列で返ります)
アップデート内容
- UTF-8 <=> JIS 変換テーブルのバグ修正 (文字化けが直りました)
- JIS X 0208 を対象にした変換テストが通るようになりました
- ファイルサイズが約60% 減りました
- 実行速度が向上しました
- convert で引数にオブジェクトが渡せるようになりました
UTF-8 <=> JIS 変換テーブルのバグ
UTF-8 から JIS, JIS から UTF-8 への変換テーブルが変なことになってました。変換テーブルは MS 基本コードポイント (Unicode) を参照していましたが、 UTF-8 に変換する際に無効なコードポイントになってしまい文字化けが発生していました。
MS 基本コードポイントと IBM 基本コードポイントの差は以下のようになっています。
コードポイント:
文字名 | IBM CP (Unicode) | MS CP (Unicode) | IBM CP (UTF-8) | MS CP (UTF-8) |
---|---|---|---|---|
― (全角ダッシュ) | U+2014 | U+2015 | E28094 | E28095 |
~ (波形ダッシュ) | U+301C | U+FF5E | E3809C | EFBD9E |
∥ (二重縦線) | U+2016 | U+2225 | E28096 | E288A5 |
- (負符号) | U+2212 | U+FF0D | E28892 | EFBC8D |
¢ | U+00A2 | U+FFE0 | C2A2 | EFBFA0 |
£ | U+00A3 | U+FFE1 | C2A3 | EFBFA1 |
¬ | U+00AC | U+FFE2 | C2AC | EFBFA2 |
encoding.js の場合、MS コードポイントのまま変換しようとしていまい、対応する文字がなく '?' などになってしまっていました。
これは元々直したつもりでいたのですが、 encoding.js 1.0.10 Line 2973 あたりを見てみると以下のようになっていて
0xEFBC8F:0x213F,0xEFBCBC:0x2140,0xE3809C:0x2141,0xEFBD9E:0x2141,0xE288A5:0x2142,そもそも 0x2141 が消しきれてなくて重複していたり、対応する JIS テーブルに文字がなくて変換すると 1文字分消えてしまったりと、 バグが多かったのですが
今回、IBM 基本コードポイントの差分によって変換してあげることで、ぶじ文字化けが解消されました。
JIS X 0208 を対象にした変換テストが通るようになりました
この変換テーブルの修正により、JIS X 0208-1997 (JIS規格 第一・第二水準漢字) を対象にした変換テスト (UTF-16, UTF-8, Shift_JIS, EUC-JP, ISO-2022-JP(JIS)) が通るようになりました。 また、Unicode サロゲートペア の処理も修正しています。ファイルサイズが約60% 減りました
encoding.js では、変換テーブルだけでかなりのサイズを占めています。前バージョンまでは、JIS→UTF-8 テーブルと UTF-8→JIS テーブルの 2つを保持していたのですが、
今回、UTF-8→JIS のみを静的に持ち、JIS→UTF-8 変換が必要になった際、動的にもう一つのテーブルを生成するようにしました。
生成されるのは呼ばれた最初の 1回のみです。
その際の速度が気になり、ベンチとってみましたが 約 2~5ms 程度で問題ないと思われます。
ファイルサイズは非minifyで 261KB (min: 219KB) だったのが 152KB (min: 116KB) になり、約60% 減らすことができました。
実行速度が向上しました
前までは、変換テーブルに文字があるかないかを、if (TABLE[c] === void 0) { ... }
みたいな感じで判断していましたが、
これは非常に遅く、また in を使うより hasOwnProperty が速く、実行環境にもよりますが
var hasOwn = Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty); if (hasOwn(obj, key)) { ... }のように bind して使うよりも hasOwnProperty.call(obj, key) のほうが若干速かったため、後者を採用しています。
変換速度は、1MB の日本語テキスト (UTF-8) に対して SJIS に文字コード変換した場合、平均 約 50ms. (EUC-JP, JIS 等も同程度)、
UNICODE (UTF-16) から UTF-8 とその逆は約 5ms ほどで、前よりだいぶ速くなりました。
convert で引数にオブジェクトが渡せるようになりました
convert の第二引数に Object を渡せるようになりました。// 以前の指定の仕方 (SJISに変換) var sjisArray = Encoding.convert(unicodeArray, 'SJIS', 'UNICODE'); // Object で指定 var sjisArray = Encoding.convert(unicodeArray, { to: 'SJIS', from: 'UNICODE' });前のように 第二引数を to, 第三引数を from として文字列で渡しても動きます。
文字化けという大きなバグを修正しているので、アップデートをおすすめします。
Download
Node.js では、encoding-japanese というモジュール名になっています
npm install encoding-japanese
var encoding = require('encoding-japanese');
上のようにして利用できます。
encoding.convert() は Buffer に対しても使えます(配列で返ります)
初心者ですみません。。
返信削除UTF-8の文字列を、SJISに変換するにはどのように記述したらよいでしょうか。
UTF-8 文字列からだと、こんな感じでしょうか。
削除// UTF-8文字列"こんにちは"
var utf8 = 'ã\u0081\u0093ã\u0082\u0093ã\u0081«ã\u0081¡ã\u0081¯';
// SJISの配列に変換
var sjis = Encoding.convert(utf8, {
to: 'SJIS',
from: 'UTF8',
type: 'array'
});
console.log(sjis); // [130, 177, 130, 241, 130, 201, 130, 191, 130, 205]
// 配列から文字列に変換
var sjisString = Encoding.codeToString(sjis);
console.log(sjisString); // ±ñÉ¿Í ←SJISで"こんにちは"