hadoop自定义输入格
来源:互联网 发布:马哥linux培训怎么样 编辑:程序博客网 时间:2024/04/28 07:34
关于hadoop的自定义输入格式:
之前在网上找过很多教程,但是大多数都是在不支持分片的前提下进行自定义输入。本文实现了一种在能够分片的基础上支持自定义输入格式的方法。
先贴代码:
import java.io.IOException;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.FSDataInputStream;import org.apache.hadoop.fs.FileSystem;import org.apache.hadoop.fs.Path;import org.apache.hadoop.fs.Seekable;import org.apache.hadoop.io.IntWritable;import org.apache.hadoop.io.Text;import org.apache.hadoop.io.compress.CodecPool;import org.apache.hadoop.io.compress.CompressionCodec;import org.apache.hadoop.io.compress.CompressionCodecFactory;import org.apache.hadoop.io.compress.Decompressor;import org.apache.hadoop.io.compress.SplitCompressionInputStream;import org.apache.hadoop.io.compress.SplittableCompressionCodec;import org.apache.hadoop.mapreduce.InputSplit;import org.apache.hadoop.mapreduce.JobContext;import org.apache.hadoop.mapreduce.RecordReader;import org.apache.hadoop.mapreduce.TaskAttemptContext;import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;import org.apache.hadoop.util.LineReader;import org.apache.hadoop.mapreduce.lib.input.FileSplit;public class ZInputFormat extends FileInputFormat<IntWritable,IntWritable>{@Overridepublic RecordReader<IntWritable, IntWritable> createRecordReader(InputSplit split, TaskAttemptContext context)throws IOException, InterruptedException {return new ZRecordReader();}//自定义的数据类型public static class ZRecordReader extends RecordReader<IntWritable,IntWritable>{//dataprivate LineReader in;//输入流private boolean more = true;//提示后续还有没有数据private IntWritable key = null;private IntWritable value = null;//这三个保存当前读取到位置(即文件中的位置)private long start;private long end;private long pos;private Log LOG = LogFactory.getLog(ZRecordReader.class);//日志写入系统,可加可不加@Overridepublic void initialize(InputSplit split, TaskAttemptContext context)throws IOException, InterruptedException {// 初始化函数FileSplit inputsplit = (FileSplit)split;start = inputsplit.getStart();//得到此分片开始位置end = start + inputsplit.getLength();//结束此分片位置final Path file = inputsplit.getPath();// 打开文件FileSystem fs = file.getFileSystem(context.getConfiguration());FSDataInputStream fileIn = fs.open(inputsplit.getPath());//关键位置2//将文件指针移动到当前分片,因为每次默认打开文件时,其指针指向开头fileIn.seek(start);in = new LineReader(fileIn, context.getConfiguration());if (start != 0) { System.out.println("4"); //关键解决位置1 //如果这不是第一个分片,那么假设第一个分片是0——4,那么,第4个位置已经被读取,则需要跳过4,否则会产生读入错误,因为你回头又去读之前读过的地方 start += in.readLine(new Text(), 0, maxBytesToConsume(start)); }pos = start;}private int maxBytesToConsume(long pos) { return (int) Math.min(Integer.MAX_VALUE, end - pos); }@Overridepublic boolean nextKeyValue() throws IOException,InterruptedException {//下一组值//tips:以后在这种函数中最好不要有输出,费时//LOG.info("正在读取下一个,嘿嘿");if(null == key){key = new IntWritable();}if(null == value){value = new IntWritable();}Text nowline = new Text();//保存当前行的内容int readsize = in.readLine(nowline);//更新当前读取到位置pos += readsize;//关键位置3//如果pos的值大于等于end,说明此分片已经读取完毕if(pos >= end){more = false;return false;}if(0 == readsize){key = null;value = null;more = false;//说明此时已经读取到文件末尾,则more为falsereturn false;}String[] keyandvalue = nowline.toString().split(",");//排除第一行if(keyandvalue[0].endsWith("\"CITING\"")){readsize = in.readLine(nowline);//更新当前读取到位置pos += readsize;if(0 == readsize){more = false;//说明此时已经读取到文件末尾,则more为falsereturn false;}//重新划分keyandvalue = nowline.toString().split(",");}//得到key和value//LOG.info("key is :" + key +"value is" + value);key.set(Integer.parseInt(keyandvalue[0]));value.set(Integer.parseInt(keyandvalue[1]));return true;}@Overridepublic IntWritable getCurrentKey() throws IOException,InterruptedException {//得到当前的Keyreturn key;}@Overridepublic IntWritable getCurrentValue() throws IOException,InterruptedException {//得到当前的valuereturn value;}@Overridepublic float getProgress() throws IOException, InterruptedException {//计算对于当前片的处理进度if( false == more || end == start){return 0f;}else{return Math.min(1.0f, (pos - start)/(end - start));}}@Overridepublic void close() throws IOException {//关闭此输入流if(null != in){in.close();}}}}
代码重要注意的几点:
1、注释为“关键位置x(1,2,3)”的三处位置,是能够实现在分片的模式下实现自定义输入的关键,这也是和网上大多数流传的教程的不同之处。
PS:写出这段代码用了2天,在网上找了不少资料,最后发现还是系统自带的输入格式文件最管用。其实对比一下,这个和KeyValueTextInputFormat类的实现大同小异,只不 过去除了压缩判定部分。
PSS:感谢那些写教程的人们~嘿嘿
0 0
- hadoop自定义输入格
- hadoop自定义文件的输入格式
- 自定义 hadoop MapReduce InputFormat 切分输入文件
- 【转】Hadoop自定义输入与输出格式
- 自定义 hadoop MapReduce InputFormat 切分输入文件
- Hadoop:自定义输入文件格式类InputFormat
- 自定义 hadoop MapReduce InputFormat 切分输入文件
- 自定义 hadoop MapReduce InputFormat 切分输入文件
- Hadoop之自定义输入数据(一)
- Hadoop自定义数据类型和输入格式
- 自定义 hadoop MapReduce InputFormat 切分输入文件
- Hadoop 自定义数据类型及输入格式
- Hadoop中MapReduce自定义输入格式
- hadoop自定义输入格式(InputFormat)
- 自定义hadoop map/reduce输入文件切割InputFormat
- 自定义hadoop map/reduce输入文件切割InputFormat
- 自定义hadoop map/reduce输入文件切割InputFormat
- 自定义hadoop map/reduce输入文件切割InputFormat
- Python程序员常用的IDE和其它开发工具
- 【cocos2D-x学习】16.A*算法
- Qt之实现360安全卫士主界面
- code::blocks中boost库的编译安装(针对菜鸟)
- Directional Lighting
- hadoop自定义输入格
- 用C++的类和结构体DIY静态链表及其接口函数
- rails time format
- MySQL数据库使用命令行备份|MySQL数据库备份命令
- java 中transient用法
- svn更改log
- pomelo报错
- 玩转Web之easyui(一)-----easy ui datagird 分页
- hash链表