TIPS:ReadJEncを使って文字エンコーディングを推定するには?[C#、VB]Webページの取得を例に、MITライセンス準拠のドネーションウェア「ReadJEnc」を使用して、文字エンコーディングを推定する方法を解説する。4.5以降)任意のWebページの内容を取得するには、現状では文字コードの推定が必要になる。TIPS:HttpClientクラスでシフトJISのWebページを取得するには?[C#、VB]」では、W3Cの推奨方式に準じて実装してみた。それには、Webページの内容を単にbyteの並びとして取得し、そのbyte列のパターンから文字エンコーディングを推定することになるだろう。本稿では、文字エンコーディングを推定して文字列に変換してくれるオープンソースのライブラリ「ReadJEnc」の使い方を解説する。文字エンコーディングを推定するライブラリバイト列のパターンから文字エンコーディングを確実に判定できるアルゴリズムは存在しない。そこで、文字コードの「自動判別」とよくいわれるが、本稿では「推定」という言葉を使うことにする。そのような文字エンコーディングを推定するライブラリはいくつも公開されている。次のようなものがある。ExplorerやFirefoxで使われているもので推定精度は高そうではあるが、C#/VBから利用するにはハードルも高い。Frameworkから直接参照できる形式のライブラリはないものか。その一つに、hnx8氏によって2014年に公開された「ReadJEnc」がある。ReadJEncはMITライセンス準拠のドネーションウェアとなっている。本稿では、Webページをbyte配列として取得し、それをReadJEncで文字列に変換する方法を紹介する。ReadJEncを利用する準備ダウンロードページから入手したzipファイルの中身を適当なフォルダーに展開しておく。その中の「Hnx8.ReadJEnc.dll」ファイルをプロジェクトの参照設定に追加すれば、準備は完了だ(次の画像)。Desktopの例である。Studioのバージョンによっては[ブラウズ]ではなく[参照])、右下の[参照]ボタン(赤枠内)をクリックする((2))。Studioの以前のバージョンでは、ダイアログのタイトルは[参照の追加]となっており、[参照]タブを選んでファイルを選択する(その場合、次の(3)はない)。出てきたファイル選択ダイアログで「Hnx8.ReadJEnc.dll」ファイル(赤枠内)を選び、[追加]ボタン(赤枠内)をクリックする((3))。[参照マネージャー]ダイアログに戻るので、右下の[OK]ボタンをクリックして完了だ((4))。StudioのIntelliSenseが機能する(次の画像)。Desktopの例である。参照設定で追加した「Hnx8.ReadJEnc.dll」ファイルと同じフォルダーに「Hnx8.ReadJEnc.xml」ファイルがあれば、このようにIntelliSenseが機能する。Webページをbyte配列として取得するには?HttpClientクラス(System.Net.Http名前空間)を利用するなら、GetByteArrayAsyncメソッドを使えばよい。TIPS:HttpClientクラスでWebページを取得するには?[C#、VB]」で作成したGetWebPageAsyncメソッドをベースにして書き換えると、次のコードのようになる。TIPS:HttpClientクラスでWebページを取得するには?[C#、VB]」で作成したGetWebPageAsyncメソッドをベースにして、メソッドが返す型を変更し、HttpClientクラスのGetStringAsyncメソッドを呼び出している部分をGetByteArrayAsyncメソッドに書き換えた。省略した部分は同じである。4.5で新設されたものだ。TIPS:WebClientクラスでWebページを取得するには?」参照)。取得したbyte配列をReadJEncで文字列に変換するには?上のメソッドで取得できたbyte配列を、ReadJEncクラスのインスタンスのGetEncodingメソッドに渡せばよい。ReadJEncクラスが文字エンコーディングを推定して文字列に変換した結果が得られる。このメソッドの返値は、推定できた文字エンコーディングとなっている(次のコード)。TIPS:HttpClientクラスでWebページを取得するには?[C#、VB]」で作成したMainメソッドに対して、太字の部分を変更/追加した。ReadJEncクラスのコンストラクターはアクセスできないようになっている。インスタンスを得るには、ReadJEncクラスの静的フィールド「JP」(日本語用)/「CN」(簡体字中国語用)などを使う。ReadJEncクラスのGetEncodingメソッドを呼び出した後は、ローカル変数「result」にエンコードされた文字列が入っている。GetEncodingメソッドの返値を格納したローカル変数「charCode」には、ReadJEncクラスが推定した文字エンコーディングが入っている。文字エンコーディングが推定できなかったときには、ローカル変数「result」/「charCode」は共にnull(C#)/Nothing(VB)になる(このサンプルコードでは省略しているが、エラー処理を行うべきである)。このサンプルコードで、WebページのURL(ローカル変数「webUri」を作るときに与える文字列、コード内では省略している)を変えて試した結果を以下に示す。日本語のサイト、あるいは他言語であってもUTF-8のサイトでは、きちんとデコードできた(次の画像)。日本語のサイト、UTF-8の他言語のサイトでは正しく推定できる上から順に、シフトJIS/JIS/EUC-JP/UTF-8(英語)/UTF-8(中国簡体字)/UTF-8(ロシア語)。中国語の一部が文字化けしているように見えるが、これはエンコードに失敗しているわけではなく、実行環境のフォント(=MSゴシック)に該当するグリフが存在しないためである。ReadJEncクラスの「JP」インスタンスでは、UTF-8ではない他言語のサイトは正しく推定できない(次の画像)。これは、言語ごとにインスタンスが分かれていることから想像できる結果である(画像にも載せたが、「CN」インスタンスを使えば中国語簡体字のエンコーディングを推定できる)。「JP」インスタンスでは、UTF-8ではない他言語のサイトは正しく推定できない上は「JP」インスタンスで、下は「CN」インスタンスでデコードした。どちらも、Webページの文字エンコーディングはGB2312(中国簡体字)である。日本語用の「JP」インスタンスは、他言語のサイトではエンコーディングを正しく推定できない。中国語簡体字用の「CN」インスタンスを使えば、簡体字のエンコーディングを推定できる(その代わりに日本語のサイトが推定できない)。TW」インスタンス/韓国語用「KR」インスタンス/欧文用「ANSI」インスタンスも用意されている。下の画像で中国語の一部が文字化けしているように見えるが、これはエンコードに失敗しているわけではなく、実行環境のフォント(=MSゴシック)に該当するグリフが存在しないためである。上述した注意点があることをわきまえて使えば、ReadJEncクラスはとても便利なライブラリである。その他、ReadJEncクラスの詳細は作者のブログ記事をご覧いただきたい。ダウンロードできるパッケージにはC#のソースコードも同梱されている。メールマガジンをご購読ください。申し込みページへITmediaはアイティメディア株式会社の登録商標です。