Java 在Hadoop MapReduce中使用WholeFileInputFormat仍然会导致映射器一次处理1行

Java 在Hadoop MapReduce中使用WholeFileInputFormat仍然会导致映射器一次处理1行,java,hadoop,mapreduce,Java,Hadoop,Mapreduce,在使用Hadoop 2.6中展开我的标题。。并且需要将整个文件发送到我的映射器,而不是一次发送一行。我遵循了《权威指南》中的Tom Whites代码,创建了WholeFileInputFormat和WholeFileRecordReader,但我的映射程序仍然一次处理一行文件。有人能看到我的代码中缺少了什么吗?我使用了我所能看到的书中的例子。任何指导都将不胜感激 WholeFileInputFormat.java public class WholeFileInputFormat extends

在使用Hadoop 2.6中展开我的标题。。并且需要将整个文件发送到我的映射器,而不是一次发送一行。我遵循了《权威指南》中的Tom Whites代码,创建了WholeFileInputFormat和WholeFileRecordReader,但我的映射程序仍然一次处理一行文件。有人能看到我的代码中缺少了什么吗?我使用了我所能看到的书中的例子。任何指导都将不胜感激

WholeFileInputFormat.java

public class WholeFileInputFormat extends FileInputFormat <NullWritable, BytesWritable>{

@Override
protected boolean isSplitable(JobContext context, Path file){
    return false;
}

@Override
public RecordReader<NullWritable, BytesWritable> createRecordReader(
        InputSplit split, TaskAttemptContext context) throws IOException, InterruptedException {
    WholeFileRecordReader reader = new WholeFileRecordReader();
    reader.initialize(split, context);
    return reader;
}
公共类WholeFileInputFormat扩展FileInputFormat{
@凌驾
受保护的布尔isSplitable(JobContext上下文,路径文件){
返回false;
}
@凌驾
公共记录阅读器createRecordReader(
InputSplit拆分,TaskAttemptContext上下文)引发IOException,InterruptedException{
WholeFileRecordReader=新的WholeFileRecordReader();
初始化(拆分,上下文);
返回读取器;
}
}

WholeFileRecordReader.java

public class WholeFileRecordReader extends RecordReader<NullWritable, BytesWritable> {
private FileSplit fileSplit;
private Configuration conf;
private BytesWritable value = new BytesWritable();
private boolean processed = false;

@Override
public void initialize(InputSplit split, TaskAttemptContext context) throws IOException, InterruptedException{
    this.fileSplit = (FileSplit) split;
    this.conf = context.getConfiguration();
}

@Override
public boolean nextKeyValue() throws IOException, InterruptedException{
    if (!processed){
        byte[] contents = new byte[(int) fileSplit.getLength()];
        Path file = fileSplit.getPath();
        FileSystem fs = file.getFileSystem(conf);
        FSDataInputStream in = null;
        try{
            in = fs.open(file);
            IOUtils.readFully(in, contents, 0, contents.length);
            value.set(contents, 0, contents.length);
        }finally{
            IOUtils.closeStream(in);
        }
        processed = true;
        return  true;
    }
    return false;
}

@Override
public NullWritable getCurrentKey() throws IOException, InterruptedException{
    return NullWritable.get();
}

@Override
public BytesWritable getCurrentValue() throws IOException, InterruptedException{
    return value;
}

@Override
public float getProgress() throws IOException {
    return processed ? 1.0f : 0.0f;
}

@Override
public void close() throws IOException{
    //do nothing :)
}
公共类WholeFileRecordReader扩展了RecordReader{
私有文件分割文件分割;
私有配置配置;
私有BytesWritable值=新的BytesWritable();
私有布尔值=false;
@凌驾
public void initialize(InputSplit split,TaskAttemptContext上下文)引发IOException、InterruptedException{
this.fileSplit=(fileSplit)split;
this.conf=context.getConfiguration();
}
@凌驾
公共布尔值nextKeyValue()引发IOException、InterruptedException{
如果(!已处理){
byte[]contents=新字节[(int)fileSplit.getLength()];
Path file=fileSplit.getPath();
FileSystem fs=file.getFileSystem(conf);
FSDataInputStream in=null;
试一试{
in=fs.open(文件);
IOUtils.readFully(in,contents,0,contents.length);
value.set(contents,0,contents.length);
}最后{
IOUtils.closeStream(in);
}
已处理=真;
返回true;
}
返回false;
}
@凌驾
public NullWritable getCurrentKey()引发IOException、InterruptedException{
返回NullWritable.get();
}
@凌驾
public BytesWritable getCurrentValue()引发IOException、InterruptedException{
返回值;
}
@凌驾
公共浮点getProgress()引发IOException{
已处理退货?1.0f:0.0f;
}
@凌驾
public void close()引发IOException{
//什么也不做:)
}
}

以及我的Mapreduce的主要方法

public class ECCCount {
public static void main(String[] args) throws Exception {

    if (args.length != 2) {
      System.out.printf("Usage: ProcessLogs <input dir> <output dir>\n");
      System.exit(-1);
    }

    //@SuppressWarnings("deprecation")
    Job job = new Job();
    job.setJarByClass(ECCCount.class);
    job.setJobName("ECCCount");

    //FileInputFormat.setInputPaths(job, new Path(args[0]));
    WholeFileInputFormat.setInputPaths(job, new Path(args[0]));
    FileOutputFormat.setOutputPath(job, new Path(args[1]));

    job.setMapperClass(ECCCountMapper.class);
    job.setReducerClass(SumReducer.class);

    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(IntWritable.class);

    boolean success = job.waitForCompletion(true);
    System.exit(success ? 0 : 1);
  }
公共类ECCCount{
公共静态void main(字符串[]args)引发异常{
如果(参数长度!=2){
System.out.printf(“用法:ProcessLogs\n”);
系统退出(-1);
}
//@抑制警告(“弃用”)
作业=新作业();
job.setJarByClass(ECCCount.class);
job.setJobName(“ECCCount”);
//setInputPaths(作业,新路径(args[0]);
setInputPath(作业,新路径(args[0]);
setOutputPath(作业,新路径(args[1]);
setMapperClass(ECCCountMapper.class);
job.setReducerClass(SumReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
布尔值success=job.waitForCompletion(true);
系统退出(成功?0:1);
}
}

还有我的制图器。现在,它只是返回作为测试用例给定的值,以查看它是否返回一行或整个文件

public class ECCCountMapper extends Mapper<LongWritable, Text, Text, IntWritable>{
@Override
  public void map(LongWritable key, Text value, Context context)
      throws IOException, InterruptedException {

      context.write(new Text(value), new IntWritable(1));
  }
公共类ECCCountMapper扩展了Mapper{
@凌驾
公共void映射(可长写键、文本值、上下文)
抛出IOException、InterruptedException{
write(新文本(值),新intwriteable(1));
}

}问题可以是mapper的输入格式。你有长写和文本。然而,在前面提到的示例中,他们使用了NullWritable、BytesWritable,因为这是WholeFileInputFormat所拥有的。此外,还需要为job.setInputFormatClass(WholeFileInputFormat.class)指定job。希望有帮助,快乐编码问题可以作为mapper的输入格式。你有长写和文本。然而,在前面提到的示例中,他们使用了NullWritable、BytesWritable,因为这是WholeFileInputFormat所拥有的。此外,还需要为job.setInputFormatClass(WholeFileInputFormat.class)指定job。希望它能有所帮助,并且愉快地编码

多亏了Ramzy的输入,我发现了错误,并通过以下更改传递了整个文件

在main方法中,我需要指定需要使用的InputFormatClass

job.setInputFormatClass(WholeFileInputFormat.class)
我的映射器需要正确的类型作为输入

public class ECCCountMapper extends Mapper<NullWritable, BytesWritable, Text, IntWritable>{
公共类ECCCountMapper扩展了Mapper{

这两个更改成功地将整个文件的一个字节[]发送到我的映射器,我在映射器中根据需要对其进行操作。

多亏了Ramzy的输入,我发现了错误,并能够通过以下更改传递整个文件

在main方法中,我需要指定需要使用的InputFormatClass

job.setInputFormatClass(WholeFileInputFormat.class)
我的映射器需要正确的类型作为输入

public class ECCCountMapper extends Mapper<NullWritable, BytesWritable, Text, IntWritable>{
公共类ECCCountMapper扩展了Mapper{

这两个更改成功地发送了一个字节[]将整个文件的所有内容发送到我的映射器,在那里我可以根据需要对其进行操作。

感谢您为我指明了正确的方向。我没有对我的类型给予足够的关注。我将为此发布我的解决方案。愉快的编码。如果有用的标志对您有所帮助,您可以使用它。如果解决了问题,请稍后接受答案。我认为您不需要声誉来接受答案:)谢谢感谢你为我指明了正确的方向。我没有对我的类型给予足够的关注。我会发布我的解决方案,这要感谢你。快乐编码。如果有用的标志对你有帮助,你可以使用它。如果问题解决了,请稍后接受答案。我认为你不需要声誉来接受答案:)