うならぼスマートフォン用の表示で見るうならぼどうも。アフィリエイトとか広告とか解析とかは/about見てね。この広告は、90日以上更新していないブログに表示しています。2017-02-28ISO-2022-JPとSJISとEUCJP(とUTF-8)をざっくり判別するアルゴリズムC#charsetの指定が適当なページがMobileSafariで文字化けするんで、XHR+FileReaderでエンコーディングを指定して読み込むブックマークレットを書いたんですが、自分で指定するのも面倒なので自動判定したいなと。既存のライブラリとかもあるんですが、どうせブックマークレットにするならシンプルなアルゴリズムを埋め込んでしまえないかなと。そもそも日本語なのかもわからないものを厳密に判定しようとすると、結局各エンコーディングでデコード(のシミュレーション)をしてみるという方法をとるようですが、今回は日本語、それも多分UTF-8でないということまでわかっています。ISO-2022-JPはESC文字(0x1B)が特徴的ですが、この文字はSJIS・EUCJP・UTF-8のいずれにおいても使いませんから、これが現れたらISO-2022-JPとほぼ断言できます。なると、あとはSJISとEUCJPの見分け方がわかれば解決しそうです。SJISとEUCJPを見比べてみるざっくり塗り分けるとこんな感じ*1。0x81-0x9FEUCJPしか考えられない領域はわずかですが、SJISしか考えられない領域は結構ありますね。)と第一水準漢字が完全に収まっているので、普通の文章ならここが使われるのはまず間違いないでしょう。0x8Eと0x8Fは別です。EUCJPでは0x8Eから始まる2バイトで半角カタカナを、0x8Fから始める3バイトで補助漢字(第三水準など)を表現します。いえ、2バイト目が0x40-0xA0の範囲であればEUCJPではないと言い切ることができます。0xA1-0xDFSJISではこの領域の1バイトで半角カナを表します。EUCJPでも非漢字と漢字の多くを含む、よく使う領域です。仮にEUCJPだとすると2バイト目もやはりSJISの半角カナ領域なので、EUCJP一文字なのかSJIS半角カナ2文字なのかを判別できません。いえ、半角カナ(と第二水準漢字以降)だけで書かれた文章はまずありません。私は読みたくないです。この領域はSJISの判断条件には使わないことにします。ここは1バイト目2バイト目共にEUCJPでよく使われるはずですから、「EUCJPっぽさ」としてカウントしてもよいでしょう。0xE0-0xFCSJIS・EUCJP共に第二水準の途中からこの領域が使われます...が、適当なサイトで文字コード表を見るとわかりますが、どちらにしても日常的に使う漢字は少ないです。一応0xEB以降はSJISでも拡張や外字でしか使われていないのでほぼEUCJPと確定できますが、前述のとおりここをわざわざチェックする甲斐は薄いです。実装してみるSJISの2バイト目はASCII領域に入ってくるので、文字の区切りを間違えると領域の判定すら面倒です。EUCJPは全てのバイトが0x80-0xFFに収まっているので、実際にコードポイントを取得しないなら文字区切りは多少無視してもよいでしょう。いうことで、SJISに沿ってポインタを進めながら、主に1バイト目を見て判断していくことにします。0x00-0x7Fと0xA1-0xDFは1バイト、それ以外は2バイトですから簡単です。適当な文字数読み込んでもSJISらしいバイトが現れなければEUCJPとします。なにで書いてもいいんですが、LINQPadで試行錯誤していたのでC#です。EUCJP;}ついでにUTF-8も0xA1-0xDFをEUCJPっぽさとしてカウントするという話をしましたが、じゃあSJISもSJISっぽさとしてカウントしたら、どちらでもないものとしてUTF-8も判定できないでしょうか。SJISの非漢字~第二水準漢字の一部。0x8EはEUC-JPの半角カナ、0x8Fは補助漢字の可能性もあるので、その場合は保留。ほとんど変わらないので割とどうでもいい。ASCII文字を巻き込んだとしても。...といっても、出現頻度は少ないだろうから、気にせずSJISに加算してもいい気はする。SJISの半角カナかEUC-JPの非漢字~第二水準漢字の一部。逆にEUC-JPならここは頻出するはずなので、この範囲が多ければEUC-JPと判断する。//2バイト目次第ではSJISと確定できる可能性もあるが、どうせ他でわかるので無視。EUC-JPで割り当てられてる文字もあまり使わない文字ばかりなので。sjisScoreの方がUTF-8食わせたときも割合が上がりやすい。Encoding.UTF8;}細かく検証したわけではありませんが、ぼちぼちいけそうです。似たようなアプローチですね。私のより細かく見ていたり、UTF8もちゃんと調べてたりします。ちなみに私のJS版というか、冒頭で触れたBookmarkletがこちら。XHRからArrayBufferで取得してるので、そのあたりは簡単になってます。Hatena::Let参考サイト塗り分け表の作成にあたっては以下のサイトが参考になりました。Safariがサポートしていないので今回は使いませんでしたが、著名なエンコーディングのエンコーダ・デコーダの具体的な実装が載っていて参考になります。丸数字などを足したShift_JIS-2004では0x85~0x86にも割り当てがあります。Standardには記載がなく、おそらくFileReaderでも使えませんが...。20:54ISO-2022-JPとSJISとEUCJP(とUTF-8)をざっくり判別するアルゴリズムTweet広告を非表示にする関連記事2018-12-31あとがきのようなもの20182018年も終わりますねえって話をします。