假设我在HDFS:上有一个文件
1
2
3
我想把它转换成
a
b
c
我写了一个地图.py:
#!/usr/bin/python
import sys
for line in sys.stdin:
print chr(int(line) + ord('a') - 1)
然后使用流式传输api:
hadoop-jar$hadoop_HOME/contrib/streaming/hadop-streaming-*.jar\
-mapper mapper.py-文件mapper.py-输入/输入-输出/输出
但输入/输出的结果是"a\t\nb\t\t\nc\t\t":
a\t
b\t\t
c\t
注意那些多余的不可打印的制表符,我用了"\t"。这里有文档:
如果行中没有制表符,那么整行都被视为关键字,并且值为null。
因此,选项卡是通过流式api作为分隔符添加的。但是,无论我如何修改与分隔符相关的选项,我都无法使其消失。
因此,我的问题是,有没有一种方法可以在没有标签等额外东西的情况下,把这项工作做得干净?
或者更清楚地说,有没有一种方法可以将hadoop用作分布式过滤器,放弃其键/值机制?
===
更新@2013.11.27
正如我和朋友们讨论的那样,实现这一目标没有简单的方法,我通过在输出中使用制表符作为字段分隔符,并在配置单元中将制表符设置为字段分隔符来解决这个问题。
我的一些朋友建议使用-D mapred.textoutputformat.ignoreseparator=true
,但这个参数不起作用。我调查了这个文件:
hadoop-1.1.2/src/mapred/org/apache/hadoop/mapred/TextOutputFormat.java
但没有找到选择。但作为另一种解决方案,流式api接受一个指定另一个输出格式的参数-outputformat
。
根据本文,您可以复制TextOutputFormat.java,删除默认的'\t',编译它,然后将其打包为jar,并使用-libjars yourjar.jar -outputformat path.to.your.outputformat
调用流式api。但我在hadoop-1.1.2中并没有成功。把这个写下来供别人参考。
您应该能够通过指定您的作业是仅映射的作业来消除这些分隔符,这本质上是您想要的分布式过滤器,并且映射器的输出将是最终输出。
要在Hadoop流中做到这一点,您可以使用以下选项:
-D mapred.reduce.tasks=0
因此,对于完整的命令,这看起来像:
hadoop jar $HADOOP_HOME/contrib/streaming/hadoop-streaming-*.jar -D mapred.reduce.tasks=0 -mapper mapper.py -file mapper.py -input /input -output /output