我需要拆分(根据某些逻辑)并分发给映射器的二进制文件集。我为此使用Hadoop 流。主要问题是通过线路发送确切的二进制块而不改变它们。事实证明,发送原始字节并非易事。
为了更好地说明问题,我编写了一个非常简单的扩展RecordReader
类,它应该从拆分中读取一些字节并发送它们。二进制数据可以包含任何内容(包括换行符)。以下是next()
可能阅读的内容:
public class MyRecordReader implements
RecordReader<BytesWritable, BytesWritable> {
...
public boolean next(BytesWritable key, BytesWritable ignore)
throws IOException {
...
byte[] result = new byte[8];
for (int i = 0; i < result.length; ++i)
result[i] = (byte)(i+1);
result[3] = (byte)'\n';
result[4] = (byte)'\n';
key.set(result, 0, result.length);
return true;
}
}
在这种情况下,每个next()
函数调用都应将以下字节序列写入标准输入:01 02 03 0a 0a 06 07 08
。如果我使用类型化字节(Hadoop-1722),那么序列应该以总共五个字节为前缀,第一个字节是序列的类型(0 表示字节),其他四个字节表示大小。所以序列应该看起来完全像这样:00
00
00
00
08
01
02
03
0a
0a
06
07
08
.
我对其进行了测试/bin/cat
以验证结果,命令如下:
hadoop jar <streaming jar location>
-libjars <my input format jar>
-D stream.map.input=typedbytes
-mapper /bin/cat
-inputformat my.input.Format
用来hexdump
查看传入的密钥我得到了这个:。正如您所看到的,每个(换行符)都以(tab)为前缀,但是键入的字节给出了(以前)关于字节序列的类型和大小的正确信息。00
00
00
00
08
01
02
03
09
0a
09
0a
06
07
08
0a
09
这给使用其他语言编写映射器带来了一个严重的问题,因为字节会在途中发生变化。
似乎无法保证字节将完全按原样发送,除非还有另一个我遗漏了什么?