FileOutputFormat
- TextOutputFormat<K,V> 默认输出字符串输出格式;
- SequenceFileOutputFormat<K,V> 序列化文件输出;
- MultipleOutputs<K,V> 可以把输出数据输送到不同的目录;
下面我们以分析FileOutputFormat为例,得到一些启迪,来满足我们的某些需要,
如修改keyvalue的分隔符,或者是修改写入文件的行分隔符 或是 重命名文件的输出名称等需求。
FileOutputFormat里面的主要方法是
最重要的方法是getRecordWriter,recordwriter 对象用于写数据。
默认名件输出来自于方法getDefaultWorkFile(),而这个方法又调用了getUniqueFile().所以重写这些方法可以实现自己想要的文件名字。
TextOutputFormat中的
private static final byte[] newline = new byte[]{'\002'}; //可用于自定义自己的new line ,例如我使用\002来做新行的标志
import org.apache.hadoop.mapreduce.lib.output.MultipleOutputs;
这个类也可以在一定程度上实现改输出的文件名的功能。但它的主要功能是其名字所表达的。
它可以同时支持多种文件类型的输出,你可以把你的输出内容分目录输出,分文件输出,文件名前缀可以自己指定。
经实验,part-r-0000可能还存在,但是已经是空的,数据已经进入到你指定的文件中去了。
使用方法其实类本身中带的usage示例已经非常清楚地说明 。
驱动类中简单写下如下的代码即可:
* // Defines additional single text based output 'text' for the job * MultipleOutputs.addNamedOutput(job, "text", TextOutputFormat.class, * LongWritable.class, Text.class); * * // Defines additional sequence-file based output 'sequence' for the job * MultipleOutputs.addNamedOutput(job, "seq", * SequenceFileOutputFormat.class, * LongWritable.class, Text.class);
然后就是需要在你的mapper类或者是reducer类中,一般是reducer类中,如果你的项目没有reduce阶段,则需要写到mapper类中。
写法如下:
private MultipleOutputs mos; * public void setup(Context context) { * ... * mos = new MultipleOutputs(context); * } * * public void reduce(WritableComparable key, Iterator<Writable> values, * Context context) * throws IOException { * ... * mos.write("text", , key, new Text("Hello")); * mos.write("seq", LongWritable(1), new Text("Bye"), "seq_a"); * mos.write("seq", LongWritable(2), key, new Text("Chau"), "seq_b"); * mos.write(key, new Text("value"), generateFileName(key, new Text("value"))); * ... * } * * public void cleanup(Context) throws IOException { * mos.close(); * ... * }