[Hadoop编程实践]解决MultipleInputs时调用getInputSplit抛出TaggedInputSplit的转换错误

今天在写MapReduce时遇到一个,和这篇文章描述的一样
 
因此直接将原文转于此,备忘。
 
==== 转载开始 ====
在社区版的hadoop版本0.19/0.20中,当使用普通的输入的时候,比如
job.setInputFormatClass(TextInputFormat.class);
 
在mapper运行的时候,可以用如下的方法得到对应的filesplit,也就能拿到对应的输入路径,等等信息.
(FileSplit)(reporter.getInputSplit()); 0.19
(FileSplit)(context.getInputSplit());0.20
 
但是如果是使用
MultipleInputs.addInputPath(job, new Path(path),
SequenceFileInputFormat.class, ProfileMapper.class);
 
在mapper中再使用上面的那种方式,就会报出一个类型转换错误
 
java.lang.ClassCastException: org.apache.hadoop.mapreduce.lib.input.TaggedInputSplit cannot be cast to org.apache.hadoop.mapreduce.lib.input.FileSplit
 
而我们需要的filesplit实际上就是TaggedInputSplit中的成员变量inputSplit
 
然而TaggedInputSplit这个类在社区版中并不是public的,所以我们并不能直接直接拿到对应的信息了.
 
不知道后续的社区版是怎么做的?可能已经修改了吧
 
我们公司使用的是0.19的加强版,采用的方式是把TaggedInputSplit声明为public,让后重新打一个包发布.这个是最简单的了.
 
(FileSplit)((TaggedInputSplit)reporter.getInputSplit()).getInputSplit(); 这样就能获得
 
另外还可以直接通过反射来获得TaggedInputSplit中的inputSplit.处理过程就不写了.
 
==== 转载结束 ====
 
我采用的是上文提到的通过反射来获取TaggedInputSplit中的inputSplit。这参考了StackOverflow上的实现,链接和代码如下:
 
private String getFilePath(Context context) throws IOException {
  // FileSplit fileSplit = (FileSplit) context.getInputSplit();
  InputSplit split = context.getInputSplit();
  Class<? extends InputSplit> splitClass = split.getClass();
  FileSplit fileSplit = null;
  if (splitClass.equals(FileSplit.class)) {
    fileSplit = (FileSplit) split;
  } else if (splitClass.getName().equals("org.apache.hadoop.mapreduce.lib.input.TaggedInputSplit")) {
    // begin reflection hackery...
    try {
      Method getInputSplitMethod = splitClass.getDeclaredMethod("getInputSplit");
      getInputSplitMethod.setAccessible(true);
      fileSplit = (FileSplit) getInputSplitMethod.invoke(split);
    } catch (Exception e) {
      // wrap and re-throw error
      throw new IOException(e);
    }
    // end reflection hackery
  }
  return fileSplit.getPath().toString();
}

  

posted on 2013-03-27 11:40  静静的三娃  阅读(2210)  评论(0编辑  收藏  举报

导航