1. 程式人生 > >MapReducer中獲取輸入檔案路徑

MapReducer中獲取輸入檔案路徑

正常情況:

在社群版的hadoop版本0.19/0.20中,當使用普通的輸入的時候,比如:

job.setInputFormatClass(TextInputFormat.class);

在mapper執行的時候,可以用如下的方法得到對應的filesplit,也就能拿到對應的"輸入路徑"等資訊

FileSplit fileSplit = (FileSplit)(reporter.getInputSplit()); 	// 版本:0.19

FileSplit fileSplit = (FileSplit)(context.getInputSplit());		// 版本:0.20
String fileName =
fileSplit.getPath().toUri().getPath();

遇到問題:

但是如果是使用:

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的,所以我們並不能直接直接拿到對應的資訊了;不知道後續的社群版是怎麼做的?可能已經修改了吧

解決辦法:

通過反射來獲得TaggedInputSplit中的inputSplit:

import java.io.IOException;
import java.lang.reflect.Method;

import org.apache.hadoop.mapreduce.InputSplit;
import org.apache.hadoop.mapreduce.Mapper.Context; import org.apache.hadoop.mapreduce.lib.input.FileSplit; public class MapperUtils { /** * 獲得輸入檔案路徑 * */ public static String getFilePath(Context context) throws IOException { 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")){ try{ Method getInputSplitMethod = splitClass.getDeclaredMethod("getInputSplit"); //設定訪問許可權 true:不需要訪問許可權檢測直接使用 false:需要訪問許可權檢測 getInputSplitMethod.setAccessible(true); fileSplit = (FileSplit) getInputSplitMethod.invoke(split); } catch (Exception e) { throw new IOException(e); } } return fileSplit.getPath().toUri().getPath(); } }

此時,通過: String filePath = MapperUtils.getFilePath(context); 即可獲取輸入檔案路徑