日本語文字コードの判別
文字コードの判別はバイナリデータの難しい処理というイメージがあったけど、そこそこの精度でいいなら意外と単純だった。
今回の方針は、半角カナは無視、UTF-8の優先度高め、という方針。
各ESC(0x1B〜)が出た場合はISO-2022-JP(確定)
http://kasumi.sakura.ne.jp/~gm/gpj/dev/tips/other/kanji.shtml
第1バイトで指定された長さ以下の場合は他コード(非UTF-8確定)
半角カナを考える必要がなければ0x80<->0xA0をチェックしてこの範囲がでればSJIS
コード本体
String.prototype.uconv = function(charset){ var u = Components.classes['@mozilla.org/intl/scriptableunicodeconverter'] .createInstance(Components.interfaces.nsIScriptableUnicodeConverter); u.charset = charset; return u; } String.prototype.convTo = function(charset){ return this.uconv(charset||'UTF-8').ConvertFromUnicode(this); } String.prototype.convFrom = function(charset){ return this.uconv(charset||this.guess()).ConvertToUnicode(this); } String.prototype.guess = function(){ if(this.match(/\x1B/)) return 'ISO-2022-JP'; try{this.convFrom('UTF-8'); return 'UTF-8'} catch(e){return this.match(/[\x80-\xA0]/) ? 'Shift_JIS' : 'EUC-JP'} }
テスト
>>> 'あ'.convTo('UTF-8').guess() "UTF-8" >>> 'あ'.convTo('ISO-2022-JP').guess() "ISO-2022-JP" >>> 'あ'.convTo('Shift_JIS').guess() "Shift_JIS" >>> 'あ'.convTo('EUC-JP').guess() "EUC-JP"
おぼえがき
ConvertToUnicodeはUTF-8からの変換時に規格外のデータを与えると例外を発生するが、
EUC-JP,Shift_JIS,ISO-2022-JPからの変換では変な文字になるだけで例外は発生しない。
ConvertToUnicodeはUTF-8からの変換時にESC(=0x1B)が入っていても例外を発生しない。