package cn.weida.hadoop.Writable;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Writable;
/**
* 序列化:是指将结构化数据对象转化为字节流以便在网路上传输或者写到磁盘进行永久存储
* 反序列化:将字节流转回结构化对象的逆过程
* 序列化用于分布式数据处理的两大领域:进程间通信,永久存储
* RPC格式化:1,紧凑(进而高效的使用存储空间) 2.快速(读/写数据的额外开销比较小) 3,可扩展(可以透明地读取老格式的数据) 4.可以互操作(以可以使用不同的语言读/写永久存储的数据)
* Writable 紧凑 速度快但不太容易用JAVA以外的语言进行扩展和使用
* public interface Writable {
* void write(DataOutput out) throws IOExcption; //将其状态吸入DataOutput二进制流
* void readFields(DataInput in) throws IOExcption; //从DataInput二进制流读取状态
* }
* @author lone
*
*/
public class TestWritable {
static {IntWritable writable = new IntWritable();
writable.set(163); //序列化163
}
/**
* 序列化
* @param writable
* @return
* @throws IOException
*/
public static byte[] serialize(Writable writable) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
DataOutputStream dataout = new DataOutputStream(out);
writable.write(dataout); //将序列化后的163写到dataout流
dataout.close();
return out.toByteArray();
}
/**
* 反序列化
* @param writable
* @param bytes
* @return
* @throws IOException
*/
public static byte[] deserialize(Writable writable , byte[] bytes) throws IOException {
ByteArrayInputStream in = new ByteArrayInputStream(bytes);
DataInputStream dataIn = new DataInputStream(in);
writable.readFields(dataIn); //反序列化dataIn二进制流
dataIn.close();
return bytes;
}
}
package cn.weida.hadoop.Writable;
import java.nio.ByteBuffer;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.security.WhitelistBasedResolver;
/**
* RawComparator 用于实现直接比较数据流中的记录
* WritableComparator 继承自 WritableComparatble类和RawComparator类
* 第一 提供对原始compare() 方法的一个默认实现,该方法能够反序列化将流中的数据进行比较的对象,并调用对象的compare() 方法
* 它充当的是RawComparator实例的工厂
*
* Java基本类型的Writable封装 char类型存储在IntWritable中 所有封装包含get() 和set() 两个方法用于读取和存储封装的值
* Java基本类型 Writable实现 序列化大小(字节)
* boolean BooleanWritable 1
* byte ByteWritable 1
* Short ShortWritable 2
* int IntWritable 4
* VintWritable 1~5 //变长
* float FloatWritabe 4
* long LongWritable 8
* VlongWritable 1~9 //变长
* double DoubleWritable 8
*
*
* Text 针对UTF-8序列化的Writable类
* Text类的索引是根据编码后字节序列中的位置实现的,并非字符串中的Unicode字符,也不是Java char的编码单元
* Text.charAt() 返回的是一个表示Unicode编码位置的int类型值。而String 返回一个char类型值
* Text.find() 该方法类似于Stringd的indexOf()
*
* 可以通过set()方法重用Text实例
* t.set(pig);
* t.toString() 将Text转换成Stirng
*
* BytesWritable 对二进制数据数组的封装 包括指定所含数据字节数的整数域(4字节) 后跟数据内容本身
* set() 方法设置内容 和Text一样 getBytes() 返回的字节数组长度可能无法体现实际大小, 通过getLength() 方法确定BytesWritable的大小
*
* NullWritable 是Writable的特殊类型 序列化长度为0 不从数据流读取数据,写入数据 在MapReduce中如果不需要使用键或值的序列化地址 ,就可以将键或值声明为NullWritable
*
* ObjectWritable 是对Java基本数据类型的通用封装 当一个字段中包含多个类型时使用
* GenericWritable 如果封装的类型数量比较少并且能够提前预知,可以通过静态数组类型的数组,并使用对序列化后的类型的引用加入位置索引来提高性能
*
* Writable集合类
* ArrayWritable 数组 toArray() 用于新建该数组的一个"浅拷贝"
* ArrayPrimitiveWritable Java基本数组类型的一个封装
* TwoDArrayWritable 二维数组
* MapWritable
* SortedMapWritable
* EnumMapWritable
* @author lone
*
*/
public class Comparable {
/**
* 遍历Text对象中的字符串
* @param args
*/
public static void main(String[] args) {
Text t = new Text("\u0041\u00DF\u6771\uD801\uDC00");
ByteBuffer buf = ByteBuffer.wrap(t.getBytes(),0,t.getLength());
int cp;
while(buf.hasRemaining()&&(cp=Text.bytesToCodePoint(buf))!=-1) { //bytesToCodePoint() 获取下一代码的位置,并返回相应的int值
System.out.println(Integer.toHexString(cp));
}
}
}
package cn.weida.hadoop.Writable;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator;
import org.apache.hadoop.io.WritableUtils;
/**
* 自定义Writable集合
* 表示一对字符串的实现
*
* @author lone
*
*/
public class TextPair implements WritableComparable<TextPair>{
private Text first;
private Text second;
public TextPair() { //默认构造方法 方便反射实力化
set(new Text(),new Text());
}
public TextPair(String first,String second) {
set(new Text(first),new Text(second));
}
public TextPair(Text fist,Text second) {
set(first,second);
}
public void set(Text first,Text second) {
this.first=first;
this.second=second;
}
public Text getFirst() {
return first;
}
public Text getSecond() {
return second;
}
@Override
public void write(DataOutput out) throws IOException {
// TODO Auto-generated method stub
first.write(out);
second.write(out);
}
@Override
public void readFields(DataInput in) throws IOException {
// TODO Auto-generated method stub
first.readFields(in);
first.readFields(in);
}
@Override
public int hashCode() { //MapReduce通过hashCode()方法选择reduce 分区
// TODO Auto-generated method stub
return first.hashCode()*163+second.hashCode();
}
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
if (obj instanceof TextPair) {
TextPair tp =(TextPair)obj;
return first.equals(tp.first)&&second.equals(tp.second);
}
return false;
}
@Override
public String toString() {
return first+"\t"+ second;
}
@Override
public int compareTo(TextPair tp) {
// TODO Auto-generated method stub
int cmp=first.compareTo(tp.first);
if (cmp!=0) {
return cmp;
}
return second.compareTo(tp.second);
}
public static class Comparator extends WritableComparator {
private static final Text.Comparator TEXT_COMPARATOR = new Text.Comparator();
public Comparator() {
super(TextPair.class);
}
@Override
public int compare(byte[] b1,int s1,int l1,byte[] b2,int s2,int l2) {
int firstL1;
try {
firstL1 = WritableUtils.decodeVIntSize(b1[s1])+readVInt(b1, s1);
int firstL2 = WritableUtils.decodeVIntSize(b1[s2])+readVInt(b2, s2);
int cmp = TEXT_COMPARATOR.compare(b1, s1,firstL1,b2,s2,firstL2);
if (cmp!=0) {
return cmp;
}
return TEXT_COMPARATOR.compare(b1, s1+firstL1,l1-firstL1,b2,s2+firstL2,l2-firstL2);
} catch (IOException e) {
// TODO Auto-generated catch block
throw new IllegalArgumentException();
}
}
}
static {
WritableComparator.define(TextPair.class, new Comparator());
}
}