Fork me on GitHub

Hadoop ファイル名の取得

  • May 30, 2008

categoryプラグインは存在しません。

環境

概要

HadoopのTextInputFormatなどを使った場合、Textに分解してくれるのは良いのですが、Mapperで処理する際に元になったファイル名を取得できません。

というわけで、ファイル名を取得する方法です。

Reporterを利用

下記のようにInputFormatを用意しなくても、Reporterから

((FileSplit)report.getInputSplit()).getPath()

とすれば、Pathが取得できました。

ただ、TextInputFormatはEncodingを指定できない(UTF-8固定)という別の問題もありますが。。

自前InputFormatを用意

Writableを用意

TextInputFormatは、LongWritableとTextを出力するようになっていますが、これを、ファイル名を含むWritableとTextを出力するように変更します。

Writableは、こんな感じ。

public class FileLongWritable extends LongWritable \{
private Path path = null;

public void setPath(Path path) \{
	this.path = path;
\}

public Path getPath() \{
	return path;
\}

public long getPos() \{
	return get();
\}

@Override
public void readFields(DataInput in) throws IOException \{
	super.readFields(in);
	path = new Path(in.readUTF());
\}

@Override
public void write(DataOutput out) throws IOException \{
	super.write(out);
	out.writeUTF(path.toString());
\}
\}

InputFormat

上記Writableを返すInputFormatを用意します。と言っても、ソースを見るとわかりますがTextInputFormatはほとんど何もしていなくて、実質の処理はLineRecordReaderがやっていますので、そっちのソースも持ってきて、

 public synchronized boolean next(FileLongWritable key, Text value) \{
   key.setPath(file);

という記述を追加してやります。

Mapperの用意

あとは、Mapperを

public static class MapClass
	implements Mapper<FileLongWritable, Text, Text, Text>, JobConfigurable \{

のような感じで用意してやれば、ファイル名が取得できるようになります。

Jobの実行

Jobを実行する際に、

	conf.setInputFormat(FileLongInputFormat.class);

という感じで、新しく用意したInputFormatを指定してやるのを忘れないように。