1.序列化
所謂的序列化,就是將結構化對象轉化為字節流,以便在網絡上傳輸或是寫道磁盤進行永久存儲。反序列化,就是將字節流轉化為結構化對象。在Java中也存在序列化,剛學Java的時候,接觸的第一個項目就是QQ聊天系統,也就是網絡編程,其中,用到的就是字符流傳輸數據,通過對象序列化,然后轉化為字符流或字節流,通過socket傳遞數據。同理,序列化在分布式數據處理的兩大領域經常出現:進程間通信和永久存儲。
在Hadoop中,系統中多個節點上進程間的通信是通過“遠程過程調用”(remote procedure call, RPC)實現的。RPC將消息序列化成二進制流后發送到遠程節點,遠程節點接着將二進制流飯序列化為原始消息。通常情況下,RPC序列化格式許緊湊、快速、可擴展、和胡操作!緊湊的格式能夠使我們充分利用數據中心中最稀缺的資源——網絡帶寬。
在Hadoop中,它使用自己的序列化框架Writable,它格式緊湊、速度快,缺點是很難用Java以外的語言來擴展。
2.Writable接口
序列化抓住兩個關鍵:序列化和反序列化。所有的都是圍繞這這兩個展開的。無非就是把結構化數據轉化為字節流或是把字節流轉化為結構化對象。
Writable接口定義了兩個接口,一個是將其狀態寫如到DataOutput二進制流,另一個是從DataInput中讀取結構化對象。
import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; public interface Writable { void write(DataOutput out) throws IOException; void readFields(DataInput in)throws IOException; }
通過一個例子,看看Writable是如何把結構化對象寫入到字節流中,以及如何從字節流中讀取結構化對象。還有就是DataOutput,DataInput是如何工作的。
Example:
1 package cn.roboson.writable; 2 3 import java.io.DataInput; 4 import java.io.DataOutput; 5 import java.io.IOException; 6 7 import org.apache.hadoop.io.Writable; 8 /* 9 * 1.Writable中兩個函數的作用 10 * 2.DataInput、DataOutput有什么用? 11 */ 12 13 public class MyWritable implements Writable{ 14 15 private int counter; 16 private long timestamp; 17 @Override 18 public void readFields(DataInput in) throws IOException { 19 // TODO Auto-generated method stub 20 21 //從DataInput 數據流中讀取值 22 this.counter=in.readInt(); 23 this.timestamp=in.readLong(); 24 } 25 26 @Override 27 public void write(DataOutput out) throws IOException { 28 // TODO Auto-generated method stub 29 //寫入到DataOutput二進制流中 30 out.writeInt(counter); 31 out.writeLong(timestamp); 32 } 33 34 public static MyWritable read(DataInput in) throws IOException { 35 MyWritable w = new MyWritable(); 36 w.readFields(in); 37 return w; 38 } 39 40 public int getCounter() { 41 return counter; 42 } 43 44 public void setCounter(int counter) { 45 this.counter = counter; 46 } 47 48 public long getTimestamp() { 49 return timestamp; 50 } 51 52 public void setTimestamp(long timestamp) { 53 this.timestamp = timestamp; 54 } 55 56 }
3.實例
通過一個特殊的類IntWritable來舉例
1 package cn.roboson.writable; 2 3 import java.io.ByteArrayInputStream; 4 import java.io.ByteArrayOutputStream; 5 import java.io.DataInputStream; 6 import java.io.DataOutputStream; 7 import java.io.IOException; 8 9 import org.apache.hadoop.io.IntWritable; 10 import org.apache.hadoop.io.Writable; 11 12 public class Writable01 { 13 14 public static void main(String[] args) throws IOException { 15 16 //IntWritable是一個特殊的Writable類,對其進行序列化 17 IntWritable writable = new IntWritable(); 18 writable.set(163); 19 20 //對InWritable的對象進行序列化為字節流,把字節流中的數據存入到一個字節數組中 21 byte[] bytes = serizlize(writable); 22 23 //判斷字節數組中的長度是否為4,一個整數占據4個字節 24 System.out.println("字節數組的長度:"+bytes.length); 25 26 //創建一個對象,將剛剛的字節數組中的數據,反序列化寫入到結構化數據中 27 IntWritable dewritable = new IntWritable(); 28 deserizlize(dewritable, bytes); 29 System.out.println(dewritable.get()); 30 } 31 32 public static byte[] serizlize(Writable writable) throws IOException{ 33 34 //創建一個輸出字節流對象 35 ByteArrayOutputStream out = new ByteArrayOutputStream(); 36 DataOutputStream dataout = new DataOutputStream(out); 37 38 //將結構化數據的對象writable寫入到輸出字節流。 39 writable.write(dataout); 40 return out.toByteArray(); 41 } 42 43 public static byte[] deserizlize(Writable writable,byte[] bytes) throws IOException{ 44 45 //創建一個輸入字節流對象,將字節數組中的數據,寫入到輸入流中 46 ByteArrayInputStream in = new ByteArrayInputStream(bytes); 47 DataInputStream datain = new DataInputStream(in); 48 49 //將輸入流中的字節流數據反序列化 50 writable.readFields(datain); 51 return bytes; 52 53 } 54 }
運行結果:

