Hadoop代码測试环境:Hadoop2.4

应用:在对数据须要进行一定条件的过滤和简单处理的时候能够使用自己定义输入文件格式类。

Hadoop内置的输入文件格式类有:

1)FileInputFormat<K,V>这个是主要的父类,我们自己定义就直接使用它作为父类;

2)TextInputFormat<LongWritable,Text>这个是默认的数据格式类,我们一般编程,假设没有特别指定的话,一般都使用的是这个;key代表当前行数据距离文件開始的距离,value代码当前行字符串;

3)SequenceFileInputFormat<K,V>这个是序列文件输入格式,使用序列文件能够提高效率,可是不利于查看结果,建议在过程中使用序列文件,最后展示能够使用可视化输出;

4)KeyValueTextInputFormat<Text,Text>这个是读取以Tab(也即是\t)分隔的数据,每行数据假设以\t分隔,那么使用这个读入,就能够自己主动把\t前面的当做key,后面的当做value;

5)CombineFileInputFormat<K,V>合并大量小数据是使用;

6)MultipleInputs,多种输入,能够为每一个输入指定逻辑处理的Mapper;

原理:

InputFormat接口有两个重要的函数:

1)getInputSplits,用于确定输入分片,当我们继承FileInputFormat时,就能够忽略此函数,而使用FileInputFormat的此函数就可以;

2)createRecordReader ,针对数据怎样读取的类,定义输入文件格式,事实上也就是定义此类;

在每一个map函数中,最開始调用的都是nextKeyValue()函数,这个函数就是在RecordReader中定义的(我们自己定义RecordReader就是使用不同的实现而已),所以这里会调用我们指定的RecordReader中的nextKeyValue函数。这个函数就会处理或者说是初始化key和value,然后返回true,告知已经处理好了。接着就会调用getCurrentKey 和getCurrentValue获取当前的key和value值。最后,返回map,继续运行map逻辑。

自己定义输入文件格式类:

package fz.inputformat;

import java.io.IOException;

import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.InputSplit;
import org.apache.hadoop.mapreduce.RecordReader;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
/**
* 自己定义输入文件读取类
*
* @author fansy
*
*/
public class CustomInputFormat extends FileInputFormat<Text, Text> { @Override
public RecordReader<Text, Text> createRecordReader(InputSplit split,
TaskAttemptContext context) throws IOException,
InterruptedException {
// TODO Auto-generated method stub
return new CustomReader();
}
}

这里看到假设继承了FileInputFormat 后,就不须要关心getInputSplits了,而仅仅须要定义RecordReader就可以。

自己定义RecordReader

package fz.inputformat;

//import java.io.BufferedReader;
import java.io.IOException; 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.io.Text;
import org.apache.hadoop.mapreduce.InputSplit;
import org.apache.hadoop.mapreduce.RecordReader;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;
import org.apache.hadoop.util.LineReader; public class CustomReader extends RecordReader<Text ,Text>{
// private BufferedReader in;
private LineReader lr ;
private Text key = new Text();
private Text value = new Text();
private long start ;
private long end;
private long currentPos;
private Text line = new Text();
@Override
public void initialize(InputSplit inputSplit, TaskAttemptContext cxt)
throws IOException, InterruptedException {
FileSplit split =(FileSplit) inputSplit;
Configuration conf = cxt.getConfiguration();
Path path = split.getPath();
FileSystem fs = path.getFileSystem(conf);
FSDataInputStream is = fs.open(path);
lr = new LineReader(is,conf); // 处理起始点和终止点
start =split.getStart();
end = start + split.getLength();
is.seek(start);
if(start!=0){
start += lr.readLine(new Text(),0,
(int)Math.min(Integer.MAX_VALUE, end-start));
}
currentPos = start;
} // 针对每行数据进行处理
@Override
public boolean nextKeyValue() throws IOException, InterruptedException {
if(currentPos > end){
return false;
}
currentPos += lr.readLine(line);
if(line.getLength()==0){
return false;
}
if(line.toString().startsWith("ignore")){
currentPos += lr.readLine(line);
} String [] words = line.toString().split(",");
// 异常处理
if(words.length<2){
System.err.println("line:"+line.toString()+".");
return false;
}
key.set(words[0]);
value.set(words[1]);
return true; } @Override
public Text getCurrentKey() throws IOException, InterruptedException {
return key;
} @Override
public Text getCurrentValue() throws IOException, InterruptedException {
return value;
} @Override
public float getProgress() throws IOException, InterruptedException {
if (start == end) {
return 0.0f;
} else {
return Math.min(1.0f, (currentPos - start) / (float) (end - start));
}
} @Override
public void close() throws IOException {
// TODO Auto-generated method stub
lr.close();
} }

这里主要是两个函数,initial和nextKeyValue。

initial主要用于初始化,包含打开和读取文件,定义读取的进度等;

nextKeyValue则是针对每行数据(因为这里使用的是LineReader,所以每次读取的是一行,这里定义不同的读取方式,能够读取不同的内容),产生相应的key和value对,假设没有报错,则返回true。这里能够看到设置了一条规则,假设输入数据是以ignore開始的话就忽略,同一时候每行仅仅取得逗号前后的数据分别作为key和value。

实战:

输入数据:

ignore,2
a,3
ignore,4
c,1
c,2,3,2
4,3,2
ignore,34,2

定义主类,主类的Mapper是默认的Mapper,没有reducer。

package fz.inputformat;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner; public class FileInputFormatDriver extends Configured implements Tool{ /**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
ToolRunner.run(new Configuration(), new FileInputFormatDriver(),args);
} @Override
public int run(String[] arg0) throws Exception {
if(arg0.length!=2){
System.err.println("Usage:\nfz.inputformat.FileInputFormatDriver <in> <out>");
return -1;
}
Configuration conf = getConf(); Path in = new Path(arg0[0]);
Path out= new Path(arg0[1]);
out.getFileSystem(conf).delete(out, true); Job job = Job.getInstance(conf,"fileintputformat test job");
job.setJarByClass(getClass()); job.setInputFormatClass(CustomInputFormat.class);
job.setOutputFormatClass(TextOutputFormat.class); job.setMapperClass(Mapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Text.class);
// job.setOutputKeyClass(LongWritable.class);
// job.setOutputValueClass(VectorWritable.class);
job.setNumReduceTasks(0);
// System.out.println(job.getConfiguration().get("mapreduce.job.reduces"));
// System.out.println(conf.get("mapreduce.job.reduces"));
FileInputFormat.setInputPaths(job, in);
FileOutputFormat.setOutputPath(job, out); return job.waitForCompletion(true)?0:-1;
} }

查看输出:

这里能够看到,ignore的数据已经被忽略掉了,同一时候每行仅仅输出了逗号前后的数据而已。

同一时候须要注意到:

这里有一行数据读入的是空字符串,这个临时还没找到原因。

总结:自己定义输入数据格式能够针对不同的数据做些过滤,进行一些简单的逻辑处理,有点相似map的功能,可是假设仅仅是这点功能的话,那全然能够使用map来代替了。事实上输入数据格式还有其它的功能,比方合并大量的小数据,以提高效率,这个在下篇再说。

分享,成长,快乐

转载请注明blog地址:http://blog.csdn.net/fansy1990

hadoop编程小技巧(5)---自己定义输入文件格式类InputFormat的更多相关文章

  1. hadoop编程小技巧(5)---自定义输入文件格式类InputFormat

    Hadoop代码测试环境:Hadoop2.4 应用:在对数据需要进行一定条件的过滤和简单处理的时候可以使用自定义输入文件格式类. Hadoop内置的输入文件格式类有: 1)FileInputForma ...

  2. hadoop编程小技巧(7)---自己定义输出文件格式以及输出到不同文件夹

    代码測试环境:Hadoop2.4 应用场景:当须要定制输出数据格式时能够採用此技巧,包含定制输出数据的展现形式.输出路径.输出文件名称称等. Hadoop内置的输出文件格式有: 1)FileOutpu ...

  3. hadoop编程小技巧(1)---map端聚合

    測试hadoop版本号:2.4  Map端聚合的应用场景:当我们仅仅关心全部数据中的部分数据时,而且数据能够放入内存中. 使用的优点:能够大大减小网络数据的传输量,提高效率: 一般编程思路:在Mapp ...

  4. Java编程小技巧(1)——方法传回两个对象

    原文地址:Java编程小技巧(1)--方法传回两个对象 | Stars-One的杂货小窝 题目是个伪命题,由Java语法我们都知道,方法要么返回一个对象,要么就不返回 当有这样的情况,我们需要返回两个 ...

  5. Shellcode编程小技巧

    工作需要,需要注入其他程序监控一些东西,检测到的数据通过WM_COPY 消息发送给显示窗体.(大体是这样的还没定稿) ##1 选择一个框架 ## tombkeeper/Shellcode_Templa ...

  6. 学会这些 pycharm 编程小技巧,编程效率提升 10 倍

    PyCharm 是一款非常强大的编写 python 代码的工具.掌握一些小技巧能成倍的提升写代码的效率,本篇介绍几个经常使用的小技巧. 一.分屏展示 当你想同时看到多个文件的时候: 1.右击标签页: ...

  7. 积累的VC编程小技巧之工具条和状态条

    1.工具条和状态条中控件的添加: 方法⑴.只能在ToolBar里创建控件:首先,在ToolBar中创建一个Button,其ID为ID_TOOL_COMBO(我们要将创建的控件放在该Button的位置上 ...

  8. 干货分享:小技巧大用处之Bean管理类工厂多种实现方式

    前言:最近几个月很忙,都没有时间写文章了,今天周末刚好忙完下班相对早点(20:00下班)就在家把之前想总结的知识点写出来,于是就有了这篇文章.虽无很高深的技术,但小技巧有大用处. 有时我们经常需要将实 ...

  9. 积累的VC编程小技巧之编辑框

    1.如何让对话框中的编辑框接收对话框的消息 ////////////////////////////////////////////////// 如何让对话框中的CEdit控件类接收对话框的消息/// ...

随机推荐

  1. NServiceBus开发

    使用NServiceBus开发分布式应用 系列主题:基于消息的软件架构模型演变 NServiceBus 是一个.Net平台下开源的消息服务框架,这类产品有时也被称作ESB(Enterprise Ser ...

  2. TCP/IP 网络精讲:OSI七层模型(第二课)

    内容简介 1.前言 2.第一部分第二课:互联网的创立,OSI七层模型 3.第一部分第三课预告:OSI第一层,连接你的机器 前言 PS:昨天做了课程大纲之后,发现这个坑挖得有点大.不过既然挖了,岂有不跳 ...

  3. openSUSE 国内镜像摘要

    1. 北交(BJTU): http://mirror.bjtu.edu.cn/opensuse http://mirror.bjtu.edu.cn/packman/suse 2. 华中科大(HUST) ...

  4. hadoop出现namenode running as process 18472. Stop it first.

    hadoop出现namenode running as process 18472. Stop it first.等等,类别似几个的出现. namenode running as process 32 ...

  5. FireFox VS Chrome 之 调试篇

    一个完美的调试工具,FireBug! 精确跟踪每一步.仅仅要按下图所看到的,选择"脚本",然后在下方选择脚本所在的文件就可以对该文本的运行进行断点跟踪. 而且仅当一个线程运行结束后 ...

  6. LeetCode之Sort List

    称号:Sort a linked list in O(n log n) time using constant space complexity. 对一个单链表进行排序,要求时间复杂度为O(n log ...

  7. Android docs4.3API

    查找在线课程,加速进入Android docs API,最主要的原因是网上加载js文件速度慢,另一种是装google字体缓慢! import java.io.BufferedReader; impor ...

  8. 二元最近的共同祖先问题(O(n) time 而且,只有一次遍历,O(1) Space (它不考虑函数调用栈空间))

    问题: 找到两个节点的二叉树的最近的共同祖先. 首先可以参考这个博客http://blog.csdn.net/cxllyg/article/details/7635992 ,写的比較具体,包含了节点包 ...

  9. android visible invisible和gone差异

    android中UI应用的开发中常常会使用view.setVisibility()来设置控件的可见性.当中该函数有3个可选值.他们有着不同的含义: View.VISIBLE--->可见 View ...

  10. Javascript J更深层次的理解avascript 基础知识

    eval全局函数 dojo loader会看到如下的功能    var eval_ = new Function('return eval(arguments[0]);'); //Function 函 ...