概要
CentOS の Docker コンテナ上で Java プログラムを動かしていたところ、日本語のファイル名を含むファイル一覧の取得で謎の文字化けが発生しました。
import java.io.*;
public class Sample {
public static void main(String[] args) {
// ファイル名が日本語のファイル「/sample/あいうえお.csv」を配置しておく
new File("/sample").listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
System.out.println(name); // => ファイル一覧を取得すると日本語ファイル名が文字化けする
return false;
}
});
}
}
ちなみに、LANG環境変数を en_US.UTF-8
とした場合は文字化けが発生せず、 ja_JP.UTF-8
とした場合は文字化けが発生することが確認できています。
本記事では日本語ファイル名の文字化けの原因と対処方法について記載します。
原因と対処方法
まず、LANG環境変数へ ja_JP.UTF-8
を設定すると文字化けが発生する原因ですが、これは Docker の CentOS イメージに日本語ロケールが登録されていないため です。
LANG環境変数に指定可能なロケールについては locale -a
コマンドから確認することができます。
CentOS イメージのコンテナ内でコマンドを実行して確認してみます。
# locale -a
C
POSIX
en_US.utf8
上記の通り、Docker の CentOS イメージのコンテナ内には日本語ロケールが含まれていません。
このコンテナ内で以下のようにLANG環境変数を指定してJavaプログラムからファイル一覧を取得しようとすると日本語ファイル名の文字化けが発生します。
LANG=ja_JP.UTF-8
export LANG
java Sample
=> 文字化けした日本語ファイル名.csv
対処方法として、 localedef
コマンドを使用して 日本語ロケールを追加する ことで文字化けが解消します。
以下のコマンドを Dockerfile の RUN 命令として追加するかコンテナ内で実行します。
# localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
もう一度 locale -a
コマンドで指定可能なロケールを確認してみます。
# locale -a
C
POSIX
en_US.utf8
ja_JP.utf8
localedef
コマンドによって ja_JP.utf8
が追加されました。
これでLANG環境変数を設定した場合も文字化けすることなく日本語のファイル名を扱えるようになります。
結論
- Docker の CentOS イメージのコンテナ内には日本語ロケールが含まれていない
- 日本語ロケールは localedef コマンドで追加できる
- 指定できない(環境に存在しない)ロケールをLANG環境変数から指定するとJavaプログラムで日本語ファイル名が文字化けする