長い人生、生きていれば文字コードの推論をやらねばならない場面が一度や二度は有るものだ(実際にはUTF-8統一時代になって、あまり発生しなくなったけど……)。
そんな時、JVM系言語であれば、juniversalchardet
が候補に上がることもあるかもしれない。
長らくバージョンアップされていないな、と思っていたら、実はフォークされたバージョンが割とこまめにメンテナンスされていた。
https://github.com/albfernandez/juniversalchardet
使い方はREADMEを読めば分かるので割愛するけど、一つだけ気を付ける点が有る。元のjuniversalchardet
はUS-ASCII
をサポートしていない。つまり、US-ASCII
に相当する文字データを渡すと、判定不能で返却された(nullが返る)。
しかし、以下のコミットでUS-ASCIIが判定できるように変更が加えられている。
https://github.com/albfernandez/juniversalchardet/commit/fcf1898ab7bae3f7308d991e225c3016e460b352
つまり、US-ASCII
という文字列が返ってくる。返却値がnull
の場合は、US-ASCII
と解釈し、UTF-8
で上書きするようなコードを書いていると、挙動が変わってしまうので、注意。
以下のコードで確かめた。
package example import org.mozilla.universalchardet.UniversalDetector object Detector { def main(argv: Array[String]): Unit = { val detector = new UniversalDetector(null) val str = "This is Love" var bytes = str.getBytes() detector.handleData(bytes, 0, bytes.length) detector.dataEnd() val encoding = detector.getDetectedCharset() if (encoding != null) { println("Detected encoding = " + encoding); } else { println("No encoding detected."); } detector.reset() } }
ThisBuild / scalaVersion := "2.13.4" ThisBuild / version := "0.1.0-SNAPSHOT" ThisBuild / organization := "com.example" ThisBuild / organizationName := "example" lazy val root = (project in file(".")) .settings( name := "Scala Seed Project", libraryDependencies ++= Seq( "com.googlecode.juniversalchardet" % "juniversalchardet" % "1.0.3", // "com.github.albfernandez" % "juniversalchardet" % "2.4.0", ) )
フォークされたバージョンが必ずしも元のバージョンと同じ挙動とは限らない点は、注意しないと(そもそも挙動を変える必要がなければフォークもしないと思うけど)