2014年11月29日

encoding.js 1.0.12 リリースしました

JavaScript 文字コード変換ライブラリ encoding.js 1.0.12 リリース しました

アップデート内容

  • 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 に対しても使えます(配列で返ります)

Demo

Repository




2 件のコメント:

  1. 初心者ですみません。。
    UTF-8の文字列を、SJISに変換するにはどのように記述したらよいでしょうか。

    返信削除
    返信
    1. 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で"こんにちは"

      削除