背景: 偽の文字エンコーディングを使用した XML ドキュメントを提供しているデータ サプライヤがいます。これは有効なエンコーディング名ではありません (ただし、本質的には ISO 8859-1 です)。このサプライヤーに形式を変更してもらうことができません。
DOM パーサーを使用してこれらの XML ドキュメントを解析しようとすると、UnsupportedEncodingException
スローされます。Charset
これはおそらく正常な動作であり、ISO-8859-1 文字エンコーディングをラップする a を記述し、CharsetProvider
それをサポートするa を記述することで回避できます。このプロバイダーを に追加するとMETA-INF/services/java.nio.charset.spi.CharsetProvider
、すべてが正常に機能し、追加のコーディングなしで Charset を使用して XML を読み取ることができます。
私が解決できない問題は次のとおりです。Hadoop にこの Charset と CharsetProvider を認識させる方法です。各レコードが上記の XML ドキュメントの 1 つである HDFS からシーケンス ファイルを読み取る Hadoop ジョブを実行しています。DOM パーサーが Charset を認識して使用することができません。システムは Java 1.6、Hadoop 0.20.2 を実行しており、XML パーサーは Java 1.6 に組み込まれた内部 Xerces パーサーです。
いくつかの追加の詳細:
次のように (「コンテキスト クラス ローダー」を使用して) CharsetProvider をコードに手動でロードすることはできますが、それでも Charset をインスタンス化できず、XML 解析に失敗します。
ClassLoader cl = Thread.currentThread().getContextClassLoader();
ServiceLoader<CharsetProvider> serviceLoader = ServiceLoader.load(CharsetProvider.class, cl);
for (CharsetProvider i : serviceLoader) {
LOG.info("CharsetProvider[1]: " + i);
}
使用可能な Charsets のリストを見ると、スタンドアロンの Java アプリとして実行するとエンコードが表示されますが、Hadoop 内で実行すると表示されません。
Set<String> charsetNames = Charset.availableCharsets().keySet();
for (String name : charsetNames) {
LOG.info("Charset: " + name);
}
以下は Hadoop では失敗しますが、それ以外の場合は機能します。
Charset cs = Charset.forName(MY_CHARSET_NAME);
Hadoop に CharsetProvider をロードするように指示する必要がある魔法の設定があると思われますが、その方法がわかりません。