在Map-reduce输出文件中获取未知整数值

时间:2017-05-23 07:41:16

标签: java hadoop mapreduce hadoop2

我正在研究一个hadoop map-reduce程序,我没有设置mapper和reducer,也没有从我的程序中为Job配置设置任何其他参数。我这样做是假设Job将输出与输出文件相同的输出。 但是我发现它在输出文件中打印了一些虚拟整数值,每一行用制表符分隔(我猜)。

这是我的代码:

import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;

public class MinimalMapReduce extends Configured implements Tool {

    public int run(String[] args) throws Exception {

        Job job = new Job(getConf());
        job.setJarByClass(getClass());
        FileInputFormat.addInputPath(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));

        return job.waitForCompletion(true) ? 0 : 1;
    }

    public static void main(String[] args) {
        String argg[] = {"/Users/***/Documents/hadoop/input/input.txt",
                            "/Users/***/Documents/hadoop/output_MinimalMapReduce"}; 
        try{
            int exitCode = ToolRunner.run(new MinimalMapReduce(), argg);
            System.exit(exitCode);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

这是输入:

2011 22
2011 25
2012 40
2013 35
2013 38
2014 44
2015 43

这是输出:

0   2011 22
8   2011 25
16  2012 40
24  2013 35
32  2013 38
40  2014 44
48  2015 43

如何获得与输入相同的输出?

2 个答案:

答案 0 :(得分:2)

  

我这样做是假设Job将输出与输出文件相同的输出

你认为这是正确的。从技术上讲,您将获得文件中的所有内容作为输出。请记住,映射器和缩减器将键值对作为输入。

映射器的输入是文件的输入分割,而减速器的输入是映射器的输出。

  

但我发现它在输出文件中打印一些虚拟整数值,每一行用制表符分隔

这些虚拟整数只不过是该行从文件开头的偏移量。由于您拥有的每一行都包含[4 DIGITS]<space>[2 DIGITS]<new-line>,因此您的偏移量是八倍。

为什么你得到这个偏移,因为你还没有定义任何映射器或减速器,你可能会问?这是因为,映射器将始终运行,这将执行将每条线映射到它的偏移量的任务,并称为IdentityMapper

  

如何获得与输入相同的输出?

您可以定义一个映射器,只需将输入行映射到输出并去除偏移量。

public void map(Object key, Text value, Context context
                    ) throws IOException, InterruptedException {
    // Some cool logic here
}

在上面的代码中,key包含虚拟整数值,即偏移量。并且value包含每行的值,一次一个。 您可以编写自己的代码,使用value函数编写context.write,然后不使用reducer并设置job.setNumReduceTasks(0)以获得所需的输出。

答案 1 :(得分:0)

我同意@ philantrovert的回答,但这里是我发现的更多细节。 根据Hadoop-The Definitive Guide,它是TextInputFormat,它将偏移量添加到行号。以下是有关TextInputFormat的文档:

  

TextInputFormat是默认的InputFormat。每条记录都是一行输入。密钥LongWritable是行开头文件中的字节偏移量。该值是该行的内容,不包括任何行终止符(例如换行符或回车符),并打包为Text对象。因此,文件包含以下文本:

On the top of the Crumpetty Tree
The Quangle Wangle sat,
But his face you could not see,
On account of his Beaver Hat.
  

分为四个记录的一个分割。记录被解释为以下键值对:

(0, On the top of the Crumpetty Tree)
(33, The Quangle Wangle sat,)
(57, But his face you could not see,)
(89, On account of his Beaver Hat.)
  

显然,密钥不是行号。这通常是不可能实现的,因为文件被分成字节而不是行边界的分割。拆分是独立处理的。行号实际上是一个连续的概念。您必须在使用它们时保留行数,因此可以知道拆分中的行号,但不能在文件中。

     

但是,每个分支的文件中的偏移量与其他分割分开是已知的,因为每个分割都知道前面分割的大小,只是将其添加到分割中的偏移量以生成全局文件偏移量。对于需要每行唯一标识符的应用程序,偏移量通常是足够的。结合文件名,它在文件系统中是唯一的。当然,如果所有线都是固定宽度,计算线数只是将偏移除以宽度。