マッパー内で入力ファイルの名前を取得するにはどうすればよいですか? 入力ディレクトリに複数の入力ファイルが保存されています。各マッパーは異なるファイルを読み取る可能性があり、マッパーがどのファイルを読み取ったかを知る必要があります。
11 に答える
First you need to get the input split, using the newer mapreduce API it would be done as follows:
context.getInputSplit();
But in order to get the file path and the file name you will need to first typecast the result into FileSplit.
So, in order to get the input file path you may do the following:
Path filePath = ((FileSplit) context.getInputSplit()).getPath();
String filePathString = ((FileSplit) context.getInputSplit()).getPath().toString();
Similarly, to get the file name, you may just call upon getName(), like this:
String fileName = ((FileSplit) context.getInputSplit()).getPath().getName();
マッパー内でこれを使用します:
FileSplit fileSplit = (FileSplit)context.getInputSplit();
String filename = fileSplit.getPath().getName();
編集 :
古い APIを使用してconfigure()内で実行する場合は、これを試してください。
String fileName = new String();
public void configure(JobConf job)
{
filename = job.get("map.input.file");
}
Hadoop Streamingを使用している場合は、ストリーミング ジョブのマッパー/リデューサーで JobConf 変数を使用できます。
マッパーの入力ファイル名については、「設定されたパラメーター」セクションを参照してください。map.input.file
変数 (マップが読み取るファイル名) は、ジョブを実行できるものです。ただし、次の点に注意してください。
注: ストリーミング ジョブの実行中に、「mapred」パラメーターの名前が変換されます。ドット ( . ) はアンダースコア ( _ ) になります。たとえば、mapred.job.id は mapred_job_id になり、mapred.jar は mapred_jar になります。ストリーミング ジョブのマッパー/リデューサーで値を取得するには、パラメーター名にアンダースコアを使用します。
たとえば、Python を使用している場合は、マッパー ファイルに次の行を追加できます。
import os
file_name = os.getenv('map_input_file')
print file_name
通常の InputFormat を使用している場合は、マッパーでこれを使用します。
InputSplit is = context.getInputSplit();
Method method = is.getClass().getMethod("getInputSplit");
method.setAccessible(true);
FileSplit fileSplit = (FileSplit) method.invoke(is);
String currentFileName = fileSplit.getPath().getName()
CombineFileInputFormat を使用している場合は、いくつかの小さなファイルを 1 つの比較的大きなファイルに結合するため、別のアプローチになります (構成によって異なります)。Mapper と RecordReader はどちらも同じ JVM で実行されるため、実行時にそれらの間でデータを渡すことができます。独自の CombineFileRecordReaderWrapper を実装し、次のようにする必要があります。
public class MyCombineFileRecordReaderWrapper<K, V> extends RecordReader<K, V>{
...
private static String mCurrentFilePath;
...
public void initialize(InputSplit combineSplit , TaskAttemptContext context) throws IOException, InterruptedException {
assert this.fileSplitIsValid(context);
mCurrentFilePath = mFileSplit.getPath().toString();
this.mDelegate.initialize(this.mFileSplit, context);
}
...
public static String getCurrentFilePath() {
return mCurrentFilePath;
}
...
次に、マッパーでこれを使用します。
String currentFileName = MyCombineFileRecordReaderWrapper.getCurrentFilePath()
私が助けてくれることを願っています:-)
古いAPIを使用する Hadoop 2.4 以降では、このメソッドが null 値を生成することに注意してください。
String fileName = new String();
public void configure(JobConf job)
{
fileName = job.get("map.input.file");
}
または、map 関数に渡された Reporter オブジェクトを利用して InputSplit を取得し、FileSplit にキャストしてファイル名を取得することもできます。
public void map(LongWritable offset, Text record,
OutputCollector<NullWritable, Text> out, Reporter rptr)
throws IOException {
FileSplit fsplit = (FileSplit) rptr.getInputSplit();
String inputFileName = fsplit.getPath().getName();
....
}
最初に型キャストによって InputSplit に変換する必要があり、次に FileSplit に型キャストする必要があります。
例:
InputSplit inputSplit= (InputSplit)context.getInputSplit();
Path filePath = ((FileSplit) inputSplit).getPath();
String filePathString = ((FileSplit) context.getInputSplit()).getPath().toString()