【MapReduce】通信数据清洗处理



MapReduce 通信数据清洗处理

现获取到一份相关人员的通信数据,进行简单的预处理整合数据,最终输出。

需求:

  1. 将电话号码替换成人名
  2. 将拨打、接听电话的时间戳转换成日期
  3. 求出电话的通话时间,以秒做单位
  4. 将省份编码替换成省份名称

数据集:
在这里插入图片描述
phone:呼叫者手机号,接受者手机号,开始时间戳,接受时间戳,呼叫者地址省份编码,接受者地址省份编码
city:地址id,省份编码,省份名称
person:电话ID,电话号码,姓名

在这里插入图片描述

最后数据的样例:

任宗阳,邓二,19700118 06:41:23,19700118 06:41:23,186,浙江省,新疆维吾尔自治区

1.封装Bean类

  • 创建Bean类:封装数据输出内容
  • 重写toString():定义输出格式
  • 继承自WritableComparable:实现序列化、反序列化方法
  • 定义setter、getter方法
  • 自定义set()方法:用于赋值
package 通信数据处理;

import org.apache.hadoop.io.WritableComparable;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

public class BeanTest implements WritableComparable<BeanTest> {
    
    

    // 封装属性
    private String sender;  // 呼叫者
    private String receiver;  // 接受者
    private String start;    // 开始时间
    private String end;      // 结束时间
    private String interval; // 间隔
    private String p;      // 省份
    private String c;     // 城市

    // toString()
    @Override
    public String toString() {
    
    
        StringBuffer buffer = new StringBuffer();
        buffer.append(sender).append(",");
        buffer.append(receiver).append(",");
        buffer.append(start).append(",");
        buffer.append(end).append(",");
        buffer.append(interval).append(",");
        buffer.append(p).append(",");
        buffer.append(c);
        return buffer.toString();
    }

    // 无参构造
    public BeanTest() {
    
    
    }

    @Override
    public int compareTo(BeanTest o) {
    
    
        return 0;
    }

    @Override
    public void write(DataOutput dataOutput) throws IOException {
    
    
        dataOutput.writeUTF(sender);
        dataOutput.writeUTF(receiver);
        dataOutput.writeUTF(start);
        dataOutput.writeUTF(end);
        dataOutput.writeUTF(interval);
        dataOutput.writeUTF(p);
        dataOutput.writeUTF(c);
    }

    @Override
    public void readFields(DataInput dataInput) throws IOException {
    
    
        sender = dataInput.readUTF();
        receiver = dataInput.readUTF();
        start = dataInput.readUTF();
        end = dataInput.readUTF();
        interval = dataInput.readUTF();
        p = dataInput.readUTF();
        c = dataInput.readUTF();
    }

    public void set(String sender, String receiver, String start, String end, String interval, String p, String c) {
    
    
        this.sender = sender;
        this.receiver = receiver;
        this.start = start;
        this.end = end;
        this.interval = interval;
        this.p = p;
        this.c = c;
    }

    public String getSender() {
    
    
        return sender;
    }

    public void setSender(String sender) {
    
    
        this.sender = sender;
    }

    public String getReceiver() {
    
    
        return receiver;
    }

    public void setReceiver(String receiver) {
    
    
        this.receiver = receiver;
    }

    public String getStart() {
    
    
        return start;
    }

    public void setStart(String start) {
    
    
        this.start = start;
    }

    public String getEnd() {
    
    
        return end;
    }

    public void setEnd(String end) {
    
    
        this.end = end;
    }

    public String getInterval() {
    
    
        return interval;
    }

    public void setInterval(String interval) {
    
    
        this.interval = interval;
    }

    public String getP() {
    
    
        return p;
    }

    public void setP(String p) {
    
    
        this.p = p;
    }

    public String getC() {
    
    
        return c;
    }

    public void setC(String c) {
    
    
        this.c = c;
    }
}

返回顶部


2.MapperTest类进行数据转换

  • 在这里我们通过缓存小文件的形式进行操作,相对来说person.txtcity.txt文件的内容较少,就将他们作为缓存文件。
  • 首先通过context.getCacheFiles()获取缓存文件组。拿person数据集举例说明:原数据集中有三列,分别是电话ID,电话号码,姓名,我们目标是将phone.txt中的前两列换成对应的号码拥有者姓名,所以在person数据集中第一列电话ID显得不那么重要(使用不到),所以在处理过程中忽略。同样的city数据集中的第一列也可以忽略~
  • 我们通过缓存的形式分别处理归属人归属地信息,并将其以电话->人名地址ID->省份的键值对形式存在两组HashMap中,这样做的好处就是后面可以通过原数据中有的信息去get()对应键的值,完成替换操作。
  • 时间数据的转换,就使用SimpleDateFormat类(指定输出样式),由于原先是String类型的数据,所以我们要先将其转为Long型的时间类型数据(Long.parseLong(String型原始数据))。时间间隔就是用结束的时间减去开始的时间即可。
package 通信数据处理;

import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import java.io.*;
import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.HashMap;

public class MapperTest extends Mapper<LongWritable, Text, BeanTest, NullWritable> {
    
    

    String sender;    // 拨号人
    String receiver;  // 接收人
    String p;         // 拨号人居住地
    String c;         // 接受者居住地
    String start;     // 拨号时间
    String end;       // 挂机时间
    String interval;  // 间隔时间
    HashMap<String, String> people = new HashMap();  // 存储人员数据缓存的内容
    HashMap<String, String> provience = new HashMap();  // 存储省份数据缓存的内容
    BeanTest k = new BeanTest();

    @Override
    protected void setup(Context context) throws IOException, InterruptedException {
    
    
        //分别获取缓存文件中的数据
        //  1.获取所有缓存文件集
        URI[] cacheFiles = context.getCacheFiles();
        String line;
        //  2.获取人员文件中的数据
        String path1 = cacheFiles[0].getPath().toString();
        BufferedReader person = new BufferedReader(new InputStreamReader(new FileInputStream(path1),"UTF-8"));
        while (StringUtils.isNotEmpty(line = person.readLine())){
    
    
            // 7,18000696806,赵贺彪
            String[] fields = line.split(",");
            people.put(fields[1],fields[2]); // 存储18000696806-->赵贺彪
        }
        //  3.获取省份文件中的数据
        String path2 = cacheFiles[1].getPath().toString();
        BufferedReader city = new BufferedReader(new InputStreamReader(new FileInputStream(path2),"UTF-8"));
        while (StringUtils.isNotEmpty(line = city.readLine())){
    
    
            // 1,110000,北京市
            String[] fields = line.split(",");
            provience.put(fields[1],fields[2]); // 存储110000-->北京市
        }
        //  4.关闭资源
        IOUtils.closeStream(person);
        IOUtils.closeStream(city);

    }

    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
    
    

        // 18620192711,15733218050,1506628174,1506628265,650000,810000 获取一行数据
        String line = value.toString();
        // 拆分
        String[] fields = line.split(",");
        // 替换拨号及接收人名信息\以及他们的所在省份信息
        sender = people.get(fields[0]);
        receiver = people.get(fields[1]);
        p = provience.get(fields[4]);
        c = provience.get(fields[5]);
        // 转换时间日期格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        start = sdf.format(Long.parseLong(fields[2]));
        end = sdf.format(Long.parseLong(fields[3]));
        interval = Long.parseLong(fields[3]) - Long.parseLong(fields[2])+"秒";
        k.set(sender,receiver,start,end,interval,p,c);
        System.out.println(k);
        // 写出
        context.write(k,NullWritable.get());
    }
}

返回顶部


3.Reducer类输出数据

package 通信数据处理;

import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;

public class ReducerTest extends Reducer<BeanTest, NullWritable,BeanTest, NullWritable> {
    
    
    @Override
    protected void reduce(BeanTest key, Iterable<NullWritable> values, Context context) throws IOException, InterruptedException {
    
    
        // 直接写出
        for (NullWritable v:values){
    
    
            context.write(key,NullWritable.get());
        }
    }
}

返回顶部


4.DriverTest类配置job

package 通信数据处理;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.net.URI;

public class DriverTest {
    
    
    public static void main(String[] args) {
    
    
        Job job;
        Configuration conf = new Configuration();
        try {
    
    
            // 获取job
            job = Job.getInstance(conf);

            // 基础配置
            job.setMapperClass(MapperTest.class);
            job.setReducerClass(ReducerTest.class);
            job.setJarByClass(DriverTest.class);
            job.setMapOutputKeyClass(BeanTest.class);
            job.setMapOutputValueClass(NullWritable.class);
            job.setOutputKeyClass(BeanTest.class);
            job.setOutputValueClass(NullWritable.class);

            // 配置缓存文件
            URI[] uris = new URI[2];
            uris[0] = new URI("file:///G:/Projects/IdeaProject-C/MapReduce/src/main/java/通信数据处理/cache/person.txt");
            uris[1] = new URI("file:///G:/Projects/IdeaProject-C/MapReduce/src/main/java/通信数据处理/cache/city.txt");
            job.setCacheFiles(uris);

            // 输入输出文件
            FileInputFormat.setInputPaths(job, new Path("G:\\Projects\\IdeaProject-C\\MapReduce\\src\\main\\java\\通信数据处理\\data\\phone.txt"));
            FileOutputFormat.setOutputPath(job, new Path("G:\\Projects\\IdeaProject-C\\MapReduce\\src\\main\\java\\通信数据处理\\output"));
            boolean b = job.waitForCompletion(true);
            System.exit(b ? 0 : 1);

        } catch (Exception e){
    
    
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

返回顶部


猜你喜欢

转载自blog.csdn.net/qq_45797116/article/details/114582563
今日推荐