我必须编写一个 map reduce 批处理(使用 org.apache.hadoop.mapreduce.*
API)来处理具有以下属性的文本文件:
- ISO-8859-1编码。
- 类似 CSV
- 分隔符是
0xef
我使用 TextInputFormat
因为我想自己执行字段拆分。然而,TextInputFormat
似乎只能处理 UTF-8 编码的文件。
根据 MAPREDUCE-232自 2008 年以来就有一个待定补丁,但我一直无法找到解决方法。我有哪些选择?事先将文件转换为 UTF-8 不是一种选择。
编辑:在阅读 Hadoop 源代码时,我想出了一个可能的解决方法。 LineReader
& friends 只处理字节。它们从不将字节转换为字符串,它们只匹配硬编码的行尾分隔符并填充字节缓冲区。由于 ISO_8859_1 和 UTF-8 为 \n
共享相同的字节序列,因此可以使用:
public class MyMapper extends Mapper<IntWritable, Text, Text, Text> {
public void map(IntWritable key, Text value, Context context)
throws IOException, InterruptedException {
String data = new String(value.getBytes(),
0, value.getLength(),
Charsets.ISO_8859_1)
// [...]
}
}
这个解决方案可以接受吗?
最佳答案
我对 TextInputFormat 没有任何特别的经验,但是如果你说的是真的(底层代码只是在寻找 \n
的单字节值),那么将这些字节转换为使用您的示例代码的字符串将是完全合法的。
更新:
您对依赖实现细节的担忧是有道理的,但是,以下几点对您有利:
- “错误修复”自 2008 年以来仍然开放,但由于未能正确处理所有编码而被拒绝(也就是说,这是一个难题,需要更多工作才能正确修复)
Text
类明确使用 utf-8 编码。以后很难在不破坏整个世界的情况下改变它。- 在第 2 点之后,由于您的目标编码具有与 utf-8 兼容的换行字节序列,只要您始终可以取回原始原始字节,就应该没问题。
关于java - TextInputFormat VS 非 UTF-8 编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15883895/