1. 项目需求

  我们取有一份学生五门课程的期末考试成绩数据,现在我们希望统计每个学生的总成绩和平均成绩。 样本数据如下所示,每行数据的数据格式为:学号、姓名、语文成绩、数学成绩、英语成绩、物理成绩、化学成绩。

19020090040 秦心芯 123 131 100 95 100
19020090006 李磊    99  92  100 90 100
19020090017 唐一建 90  99  100  89 95
19020090031 曾丽丽 100 99   97  79 96
19020090013 罗开俊 105 115  94  45 100
19020090039 周世海 114 116  93  31 97
19020090020 王正伟 109  98  88  47 99
19020090025 谢瑞彬 94  120  100 50 73
19020090007 于微     89   78  100 66 99
19020090012 刘小利  87  82   89 71 99

下面我们需要编写程序,实现自定义输入并求出每个学生的总成绩和平均成绩。

2. 项目实现

  第一步:为了便于每个学生学习成绩的计算,这里我们需要自定义一个 ScoreWritable 类实现 WritableComparable 接口,将学生各门成绩封装起来。

/**
*
*/
package com.hadoop.InputFormat; import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException; import org.apache.hadoop.io.WritableComparable; /**
* @author Zimo
* 编写学习成绩读写自定义类ScoreWritable,实现WritableComparable接口中的方法
* 数据格式参考:19020090017 name 90 99 100 89 95
*
*/
public class ScoreWritable implements WritableComparable<Object>{ private float Chinese;
private float Math;
private float English;
private float Physics;
private float Chemistry; //无参构造器
public ScoreWritable() {} //重载构造函数
public ScoreWritable(float Chinese,float Math,float English,float Physics,float Chemistry) {
this.Chinese = Chinese;
this.Math = Math;
this.English = English;
this.Physics = Physics;
this.Chemistry = Chemistry;
} // set/get方法
public float getChinese() {
return Chinese;
} public void setChinese(float chinese) {
Chinese = chinese;
} public float getMath() {
return Math;
} public void setMath(float math) {
Math = math;
} public float getEnglish() {
return English;
} public void setEnglish(float english) {
English = english;
} public float getPhysics() {
return Physics;
} public void setPhysics(float physics) {
Physics = physics;
} public float getChemistry() {
return Chemistry;
} public void setChemistry(float chemistry) {
Chemistry = chemistry;
} @Override
public void readFields(DataInput in) throws IOException {
// TODO Auto-generated method stub
Chinese = in.readFloat();
Math = in.readFloat();
English = in.readFloat();
Physics = in.readFloat();
Chemistry = in.readFloat();
} @Override
public void write(DataOutput out) throws IOException {
// TODO Auto-generated method stub
out.writeFloat(Chinese);
out.writeFloat(Math);
out.writeFloat(English);
out.writeFloat(Physics);
out.writeFloat(Chemistry);
} @Override
public int compareTo(Object arg0) {
// TODO Auto-generated method stub
return ;
} }

  第二步:自定义输入格式 ScoreInputFormat 类,首先继承 FileInputFormat,然后分别重写 isSplitable() 方法和 createRecordReader() 方法。 需要注意的是,重写createRecord Reader()方法,其实也就是重写其返回的对象ScoreRecordReader。ScoreRecordReader 类继承 RecordReader,实现数据的读取。

/**
*
*/
package com.hadoop.InputFormat; 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.mapred.FileSplit;
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;
import org.apache.hadoop.util.LineReader; /**
* @author Zimo
* 自定义学生成绩读写类InputFormat,继承自FileInputFormat接口,并实现其中的方法
*
*/
public class ScoreInputFormat extends FileInputFormat<Text, ScoreWritable> { @Override
public RecordReader<Text, ScoreWritable> createRecordReader(InputSplit arg0, TaskAttemptContext arg1)
throws IOException, InterruptedException {
// TODO Auto-generated method stub
return new ScoreRecordreader();//RecordReader 中的两个参数分别填写我们期望返回的key/value类型,我们期望key为Text类型,
//value为ScoreWritable类型封装学生所有成绩
} public static class ScoreRecordreader extends RecordReader<Text, ScoreWritable> { public LineReader in;//行读取器
public Text key;//自定义key类型
public ScoreWritable value;//自定义value类型
public Text line;//每行数据类型 @Override
public void close() throws IOException {
// TODO Auto-generated method stub
if (in != null) {
in.close();
} } @Override
public Text getCurrentKey() throws IOException, InterruptedException {
// TODO Auto-generated method stub
return key;
} @Override
public ScoreWritable getCurrentValue() throws IOException, InterruptedException {
// TODO Auto-generated method stub
return value;
} @Override
public float getProgress() throws IOException, InterruptedException {
// TODO Auto-generated method stub
return ;
} @Override
public void initialize(InputSplit input, TaskAttemptContext context) throws IOException, InterruptedException {
// TODO Auto-generated method stub
FileSplit split = (FileSplit)input;
Configuration job = context.getConfiguration();
Path file = split.getPath();
FileSystem fs = file.getFileSystem(job); FSDataInputStream filein = fs.open(file);
in = new LineReader(filein, job);
line = new Text();
key = new Text();
value = new ScoreWritable();
} //此方法读取每行数据,完成自定义的key和value
@Override
public boolean nextKeyValue() throws IOException, InterruptedException {
// TODO Auto-generated method stub
int linesize = in.readLine(line);
if (linesize == ) {
return false;
}
String[] pieces = line.toString().split("\\s+");//解析每行数据,根据空格划分
if (pieces.length != ) {
throw new IOException("Invalid record received");
} //将学生的每门成绩转换为 float 类型
float a, b, c, d, e;
try{
a = Float.parseFloat(pieces[].trim());
b = Float.parseFloat(pieces[].trim());
c = Float.parseFloat(pieces[].trim());
d = Float.parseFloat(pieces[].trim());
e = Float.parseFloat(pieces[].trim());
} catch(NumberFormatException exception) {
throw new IOException("Error parsing floating poing value in record");
}
key.set(pieces[] + "\t" + pieces[]);//完成自定义key数据
//封装自定义value数据
value.setChinese(a);
value.setMath(b);
value.setEnglish(c);
value.setPhysics(d);
value.setChemistry(e);
return true;
} } }

  在上述类中,我们只需根据自己的需求,重点编写nextKeyValue()方法即可,其它的方法比较固定,仿造着编码就可以了。

  第三步:编写 MapReduce 程序,统计学生总成绩和平均成绩。这里 MapReduce 程序仿造前面模板编写就可以了,很简单。

/**
*
*/
package com.hadoop.InputFormat; import java.io.IOException; import org.apache.commons.collections.map.StaticBucketMap;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.FileSystem;
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.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner; /**
* @author Zimo
* 学生成绩统计Hadoop程序
*
*/
public class ScoreCount extends Configured implements Tool { public static class ScoreMapper extends Mapper<Text, ScoreWritable, Text, ScoreWritable> { @Override
protected void map(Text key, ScoreWritable value, Context context)throws IOException, InterruptedException
{
context.write(key, value);
} } public static class ScoreReduce extends Reducer<Text, ScoreWritable, Text, Text> { private Text text = new Text(); protected void reduce(Text key, Iterable<ScoreWritable> Values, Context context) throws IOException, InterruptedException {
float totalScore = 0.0f;
float averageScore = 0.0f;
for(ScoreWritable ss:Values) {
totalScore = ss.getChinese() + ss.getMath() + ss.getEnglish() + ss.getPhysics() + ss.getChemistry();
averageScore += totalScore/;
}
text.set(totalScore + "\t" + averageScore);
context.write(key, text);
}
} /**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
String[] args0 =
{
"hdfs://Centpy:9000/score/score.txt",
"hdfs://Centpy:9000/score/out/"
};
int ec = ToolRunner.run(new Configuration(), new ScoreCount(), args0);
System.exit(ec); } @Override
public int run(String[] args) throws Exception {
// TODO Auto-generated method stub
Configuration conf = new Configuration();//读取配置文件 //创建输出路径
Path myPath = new Path(args[]);
FileSystem hdfs = myPath.getFileSystem(conf); if (hdfs.isDirectory(myPath)) {
hdfs.delete(myPath, true);
} Job job = new Job(conf, "ScoreCount");//新建任务
job.setJarByClass(ScoreCount.class);//设置主类
FileInputFormat.addInputPath(job, new Path(args[]));// 输入路径
FileOutputFormat.setOutputPath(job, new Path(args[]));// 输出路径
job.setMapperClass(ScoreMapper.class);// Mapper
job.setReducerClass(ScoreReduce.class);// Reducer job.setMapOutputKeyClass(Text.class);// Mapper key输出类型
job.setMapOutputValueClass(ScoreWritable.class);// Mapper value输出类型 job.setInputFormatClass(ScoreInputFormat.class);//设置自定义输入格式 job.waitForCompletion(true); return ;
} }

3. 项目测试

  输入文件如下:

  运行后结果如图:

  结果中出现了乱码!为什么会有这种情况呢?因为MapReduce采用的默认编码方式是UTF-8,而我上传的输入文件中有中文且不是采用UTF-8编码格式,所以会出现乱码。解决方法如下。

  并且,为了保证编码格式一致,先检查eclipse编码格式是否为UTF-8,不是则修改eclipse编码格式为UTF-8。Windows -> Preferences。

  最后,重新运行一次,结果如下。

  打包到Hadoop集群上运行结果也是一样的。注意:打包前作以下改动。

  到此,项目就完美地结束了。

以上就是博主为大家介绍的这一板块的主要内容,这都是博主自己的学习过程,希望能给大家带来一定的指导作用,有用的还望大家点个支持,如果对你没用也望包涵,有错误烦请指出。如有期待可关注博主以第一时间获取更新哦,谢谢!

版权声明:本文为博主原创文章,未经博主允许不得转载。

MapReduce实战:自定义输入格式实现成绩管理的更多相关文章

  1. hadoopMR自定义输入格式

    输入格式 1.输入分片与记录  2.文件输入  3.文本输入  4.二进制输入  5.多文件输入  6.数据库格式输入 详细的介绍:https://blog.csdn.net/py_123456/ar ...

  2. MapReduce的输入格式

    1. InputFormat接口 InputFormat接口包含了两个抽象方法:getSplits()和creatRecordReader().InputFormat决定了Hadoop如何对文件进行分 ...

  3. Hadoop MapReduce编程 API入门系列之自定义多种输入格式数据类型和排序多种输出格式(十一)

    推荐 MapReduce分析明星微博数据 http://git.oschina.net/ljc520313/codeexample/tree/master/bigdata/hadoop/mapredu ...

  4. MapReduce输入格式

    文件是 MapReduce 任务数据的初始存储地.正常情况下,输入文件一般是存储在 HDFS 里面.这些文件的格式可以是任意的:我们可以使用基于行的日志文件, 也可以使用二进制格式,多行输入记录或者其 ...

  5. Hadoop MapReduce编程 API入门系列之MapReduce多种输入格式(十七)

    不多说,直接上代码. 代码 package zhouls.bigdata.myMapReduce.ScoreCount; import java.io.DataInput; import java.i ...

  6. Hadoop(七):自定义输入输出格式

    MR输入格式概述 数据输入格式 InputFormat. 用于描述MR作业的数据输入规范. 输入格式在MR框架中的作用: 文件进行分块(split),1个块就是1个Mapper任务. 从输入分块中将数 ...

  7. (注意输入格式)bistuoj(旧)1237 成绩统计

    成绩统计 Time Limit(Common/Java):1000MS/3000MS          Memory Limit:65536KByteTotal Submit:88          ...

  8. DDD实战成绩管理---用户故事

    本次DDD实践选取我们都熟悉的高校成绩管理作为例子. (一).需求描述 每学期学校教务处老师会进行教学安排,具体就是建立教学班,指定该教学班代课教师,上课学生,然后进行排课(忽略此部分,这是另一个系统 ...

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

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

随机推荐

  1. 我的SIP开发之路

    http://hi.baidu.com/ltlovelty/blog/item/837baf1ece7fc6f11ad57647.html 经过对SIP协议和开源协议栈快半年的研究,我现在终于有点入门 ...

  2. C#的闭包

    简单的理解:闭包变量是把局部变量的作用域扩展到回调函数,发生在匿名方法注册到委托上,而匿名方法中使用外部的局部变量 说什么都不如图示那么容易明白啊 先看C#的源码 class Program { st ...

  3. js数组中的reverse()方法

    reverse方法是将数组中的元素的顺序进行反转,在原数组上操作,然后返回原数组.由于本人是学习js的新人,对reverse函数进行了几个小实验,以下实验均在Chrome浏览器上运行 实验一:reve ...

  4. CUDA计时

    from:http://blog.sina.com.cn/s/blog_45209f340101341e.html <1>使用cutil.h中的函数 unsigned int timer= ...

  5. zookeeper相关知识的总结:

    一.分布式协调技术 在给大家介绍ZooKeeper之前先来给大家介绍一种技术——分布式协调技术.那么什么是分布式协调技术?那么我来告诉大家,其实分布式协调技术 主要用来解决分布式环境当中多个进程之间的 ...

  6. springboot thymeleaf org.xml.sax.SAXParseException错误

    SpringBoot越来越受欢迎,而官方推荐的模板是thymeleaf ,但是其语法太过严格,使用过程中一不留心就会出现org.xml.sax.SAXParseException错误 其中主要是下面这 ...

  7. Oracal主键 唯一报错

    ORA-00001: 违反唯一约束条件 --解决方法 2017年07月27日 12:04:11 阅读数:11853 1.错误 Caused by: java.sql.BatchUpdateExcept ...

  8. 8、SRR数据下载https://ftp-trace.ncbi.nlm.nih.gov/sra/sdk/2.8.2/

    1.prefetch SRRxxxxxx         -/ncbi/public/sra 2.fastq-dump --split-files xxxxxxsra 3.SRA.SAM以及Fastq ...

  9. (分享)一位资深程序员大牛给予Java初学者的学习路线建议

    摘自:http://bbs.itheima.com/thread-333038-1-1.html 如果你是在校学生,务必要在学好基础(比如计算机系统.算法.编译原理等等)的前提下,再考虑去进行下面的学 ...

  10. 怀旧系列(1)----FBasic

    小时候,老爸斥巨资给我买了一台小霸王学习机.玩遍了所有游戏后,里面有个F-Basic语言,黑乎乎的,一点也不好玩.直到杰兄从学校带回一本BASIC语言,才知道这玩意儿还可以编辑**图案.由于没有人指导 ...