hadoop中国語出力文字化けしを解決(二)
3579 ワード
hadoopは出力テキストのデフォルト出力符号化に関してBOMのないUTF-8の形式で統一されており、ファイルのBOMでのみUTF-8として符号化されたファイルを識別できるソフトウェアが多いため、このようなソフトウェアでファイルを開くと文字化けして表示される.ファイル内容を正常に表示するためには、出力内容がファイル内に入る前にBOM(0 xEFBBBF)に書き込めばよい.
Map Reduceの実行結果は、次の関数を使用して出力ファイルを1つのファイルにまとめるカラムファイルです.
org.apache.hadoop.fs.FileUtil.copyMerge(FileSystem srcFS, Path srcDir, FileSystem dstFS, Path dstFile, boolean deleteSource, Configuration conf, String addString)
コードは次のとおりです.
/** Copy all files in a directory to one output file (merge). */
public static boolean copyMerge(FileSystem srcFS, Path srcDir,
FileSystem dstFS, Path dstFile,
boolean deleteSource,
Configuration conf, String addString) throws IOException {
dstFile = checkDest(srcDir.getName(), dstFS, dstFile, false);
if (!srcFS.getFileStatus(srcDir).isDirectory())
return false;
OutputStream out = dstFS.create(dstFile);
try {
FileStatus contents[] = srcFS.listStatus(srcDir);
Arrays.sort(contents);
for (int i = 0; i < contents.length; i++) {
if (contents[i].isFile()) {
InputStream in = srcFS.open(contents[i].getPath());
try {
IOUtils.copyBytes(in, out, conf, false);
if (addString!=null)
out.write(addString.getBytes("UTF-8"));
} finally {
in.close();
}
}
}
} finally {
out.close();
}
if (deleteSource) {
return srcFS.delete(srcDir, true);
} else {
return true;
}
}
12行目に次のコードを追加すると、UTF-8 BOMへの書き込みが完了します.
out.write(new byte[]{(byte)0xEF,(byte)0xBB,(byte)0xBF});
最終的な結果は次のとおりです.
/** Copy all files in a directory to one output file (merge). */
public static boolean copyMerge(FileSystem srcFS, Path srcDir,
FileSystem dstFS, Path dstFile,
boolean deleteSource,
Configuration conf, String addString) throws IOException {
dstFile = checkDest(srcDir.getName(), dstFS, dstFile, false);
if (!srcFS.getFileStatus(srcDir).isDirectory())
return false;
OutputStream out = dstFS.create(dstFile);
out.write(new byte[]{(byte)0xEF,(byte)0xBB,(byte)0xBF}); // BOM
try {
FileStatus contents[] = srcFS.listStatus(srcDir);
Arrays.sort(contents);
for (int i = 0; i < contents.length; i++) {
if (contents[i].isFile()) {
InputStream in = srcFS.open(contents[i].getPath());
try {
IOUtils.copyBytes(in, out, conf, false);
if (addString!=null)
out.write(addString.getBytes("UTF-8"));
} finally {
in.close();
}
}
}
} finally {
out.close();
}
if (deleteSource) {
return srcFS.delete(srcDir, true);
} else {
return true;
}
}