Golangで文字コード判定


Kobito for Windows が公開されたので、動作確認と自作プログラムの宣伝も含めて一つ記事を投稿してみます。

最近Golangで「HighBatch」 というバッチ管理用のJobSchedulerを作っているんですけど、その中で文字コードの判定が必要になってきました。

LinuxもOSXもWindowsもサーポートしようとすると、WindowsでのSJISファイルが問題になってきます。
他のOSだったら仮にEUCJPとかで問題になっても「今どきEUCJPかよ、UTF8にしろよ」って言えば済むのですが、Windowsだけはどうにもなりません(もしかして環境変数とかで変えられる?)。

そこでSJISとUTF8の判定だけでもいいので文字コードを推測(Guess)できるライブラリを探してみたのですが、標準では持ってない感じですね。

他にいい方法がないか探したところ、なかなかいい情報が無い。

そんな中、 @mattn さんの jvgrep の中で日本語の文字コードを推測してるコードを見つけました。

該当のコードは jvgrep.goの212行目 あたりになります。

上記のコードの中ではUTF16の判定やGrep作業なんかも入っているのですが、要は候補の文字コードでバッファに書き込んでみてエラーが発生しなければその文字コードは正しいと判断しているようです。

該当箇所を簡単にして抜き出してみると、

golang.go
func readAssets(str string) (string, error) {
    body, err := ioutil.ReadFile(str)
    if err != nil {
        return "", err
    }

    var f []byte
    encodings := []string{"sjis", "utf-8"}
    for _, enc := range encodings {
        if enc != "" {
            ee, _ := charset.Lookup(enc)
            if ee == nil {
                continue
            }
            var buf bytes.Buffer
            ic := transform.NewWriter(&buf, ee.NewDecoder())
            _, err := ic.Write(body)
            if err != nil {
                continue
            }
            err = ic.Close()
            if err != nil {
                continue
            }
            f = buf.Bytes()
            break
        }
    }
    return string(f), nil
}

な感じで、SJISかUTF8かを判定してUTF8の文字列を取得できるようです。

実際に開発中の HighBatch でもSJISとUTF8の判定に利用していますが問題さそうです。

出来れば Golang の基本ライブラリだけで推測して自動変換してもらえると楽なんですけど、自動変換はバグの温床になりそうなので将来的にも対応はなさそうですね。

ちなみに、 HighBatch

WebUI を持ったバッチ処理等を管理するシンプルなジョブスケジュールシステム

です。

興味のある方は こちらのスライド もどうぞ!

以上、Golangでの文字コード判定方法 と HighBatch の宣伝でした。