はじめに

JavaScript でバイナリから文字列を取り出したら Shift JIS だったなんてことよくありますよね。
そういう文字列もさっと表示したいことがあります。

読み込む方法はいくつかある

これらの文字列を読み込む方法はいくつかあって、自分が把握してるだけでも以下のものがあります。

  1. Shift JIS と UTF-16 の対応表をつくる
  2. Blob, File API を使って読み込む
  3. script, Data URL を使って変換

1, 2 の方法についてはそれぞれ解説や実装があるのですが、3 の方法については見当たらなかったので説明してみます。

準備

念のため 2 段階で文字コードの識別を試みます。

script 要素の charset 属性

script 要素には charset 属性というのがあって、この属性がセットされていた場合、指定された文字コードとして読み込みます。
仕様では Scripts in HTML documents(HTML4) や Scripts in HTML documents にかかれています。

Data URL

Data URL は The "data" URL scheme ( RFC2397 ) で定義されている、データを Web ページに埋め込むための URI Scheme です。
フォーマットはシンプルで

data:[<mediatype>][;base64],<data>

となっています。
このフォーマットの <mediatype> は以下のようなものになっています。

mediatype  := [ type "/" subtype ] *( ";" parameter )

ここから少し仕様を追っていくのが大変なので、簡単に説明すると mediatype には text/plain のような MIME Type だけではなく、text/plain; charset=Shift_JIS のように文字コードを指定する事ができます。
parameterattributevalue について詳しく知りたい方は RFC2045 を参照してください。
ちなみに mediatype が指定されていない場合のデフォルト値は text/plain; charset=us-ascii となります。

変換を行う

script 要素と Data URL について説明したので、ここからそれを使って以下のように文字コードを変換します。

  1. 変換前の文字列を文字列リテラルの文字列に変換する ( hoge という文字を 'hoge' という文字列に変換)
    • いくつかの文字は文字列リテラルとして正しくなるようにエスケープしてやる
      • バックスラッシュは \\
      • クオートは \x27
      • LF は \x0a
      • CR は \x0d
  2. 変換後の文字列を受ける callback function を作る
    • 例えば以下のような感じです
    • function Callback(str) {
      console.log(str);
      }
  3. 生成された文字列リテラルを引数にして callback function の呼び出しを行うスクリプト文字列を生成する
    • "Callback('hoge');"
  4. 生成されたスクリプト文字列を Data URL に変換して script 要素で呼び出す
    • もちろん、Data URL と script は charset 指定する

欠点

script 要素の生成と追加を行っているので非同期でしか使えません。
同期で変換したい場合はぽりごんさんのライブラリを使うと良いと思います。

おまけ

これらをまとめてやってくれる azoth.js というのを作りました。
自分でやるのめんどくさいという人はどうぞ。

ちなみに JavaScript の文字列 (UTF-16) から UTF-8 への変換と、UTF-8 からの変換は、escape/unescape, encodeURIComponent/decodeURIComponent で行う事ができるのでライブラリが必要なかったりします。

おわりに

一応簡単なテストなどもしていますが、もし考慮漏れなどありましたらお知らせください。