序列化從頭說
在面向?qū)ο蟪绦蛟O(shè)計(jì)中议薪,類是個(gè)很重要的概念尤蛮。所謂“類”,可以將它想像成建筑圖紙斯议,而對(duì)象就是根據(jù)圖紙蓋的大樓产捞。類,規(guī)定了對(duì)象的一切哼御。根據(jù)建筑圖紙?jiān)旆孔优髁伲w出來的就是大樓,等同于將類進(jìn)行實(shí)例化恋昼,得到的就是對(duì)象看靠。
一開始疗隶,在源代碼里词顾,類的定義是明確的往核,但對(duì)象的行為有些地方是明確的族操,有些地方是不明確的碾阁。對(duì)象里不明確地方科盛,是因?yàn)閷?duì)象在運(yùn)行的時(shí)候兄世,需要處理無法預(yù)測(cè)的事情甜孤,諸如用戶點(diǎn)了下屏幕老速,用戶點(diǎn)了下按鈕粥喜,輸入點(diǎn)東西,或者需要從網(wǎng)絡(luò)發(fā)送接收數(shù)據(jù)之類的橘券。后來额湘,引入了泛型的概念之后,類也開始不明確了约郁,如果使用了泛型缩挑,直到程序運(yùn)行的時(shí)候,才知道究竟是哪種對(duì)象需要處理鬓梅。
對(duì)象可以很復(fù)雜供置,也可以跟時(shí)序相關(guān)。一般來說绽快,“活的”對(duì)象只生存在內(nèi)存里芥丧,關(guān)機(jī)斷電就沒有了紧阔。一般來說,“活的”對(duì)象只能由本地的進(jìn)程使用续担,不能被發(fā)送到網(wǎng)絡(luò)上的另外一臺(tái)計(jì)算機(jī)擅耽。
序列化,可以存儲(chǔ)“活的”對(duì)象物遇,可以將“活的”對(duì)象發(fā)送到遠(yuǎn)程計(jì)算機(jī)乖仇。
把“活的”對(duì)象序列化,就是把“活的”對(duì)象轉(zhuǎn)化成一串字節(jié)询兴,而“反序列化”乃沙,就是從一串字節(jié)里解析出“活的”對(duì)象。于是诗舰,如果想把“活的”對(duì)象存儲(chǔ)到文件警儒,存儲(chǔ)這串字節(jié)即可,如果想把“活的”對(duì)象發(fā)送到遠(yuǎn)程主機(jī)眶根,發(fā)送這串字節(jié)即可蜀铲,需要對(duì)象的時(shí)候,做一下反序列化属百,就能將對(duì)象“復(fù)活”了记劝。
將對(duì)象序列化存儲(chǔ)到文件,術(shù)語又叫“持久化”诸老。將對(duì)象序列化發(fā)送到遠(yuǎn)程計(jì)算機(jī)隆夯,術(shù)語又叫“數(shù)據(jù)通信”。
Java對(duì)序列化提供了非常方便的支持别伏,在定義類的時(shí)候蹄衷,如果想讓對(duì)象可以被序列化,只要在類的定義上加上了”implements Serializable”即可厘肮,比如說愧口,可以這么定義”public class Building implements Serializable”,其他什么都不要做类茂,Java會(huì)自動(dòng)的處理相關(guān)一切耍属。Java的序列化機(jī)制相當(dāng)復(fù)雜,能處理各種對(duì)象關(guān)系巩检。
Java的序列化機(jī)制的缺點(diǎn)就是計(jì)算量開銷大厚骗,且序列化的結(jié)果體積大太,有時(shí)能達(dá)到對(duì)象大小的數(shù)倍乃至十倍兢哭。它的引用機(jī)制也會(huì)導(dǎo)致大文件不能分割的問題领舰。這些缺點(diǎn)使得Java的序列化機(jī)制對(duì)Hadoop來說是不合適的。于是Hadoop設(shè)計(jì)了自己的序列化機(jī)制。
為什么序列化對(duì)Hadoop很重要冲秽?因?yàn)镠adoop在集群之間進(jìn)行通訊或者RPC調(diào)用的時(shí)候舍咖,需要序列化,而且要求序列化要快锉桑,且體積要小排霉,占用帶寬要小。所以必須理解Hadoop的序列化機(jī)制民轴。
2. Hadoop的序列化接口
什么是接口攻柠?簡答來說,接口就是規(guī)定杉武,它規(guī)定類必須實(shí)現(xiàn)的方法辙诞。一個(gè)接口可以包含多干個(gè)方法辙售。如果一個(gè)類說自己實(shí)現(xiàn)了某個(gè)接口轻抱,那么它必須實(shí)現(xiàn)這個(gè)接口里的所有方法。特殊情況下旦部,接口也可以沒有任何方法祈搜。
Writable接口,也就是org.apache.hadoop.io.Writable接口士八。Hadoop的所有可序列化對(duì)象都必須實(shí)現(xiàn)這個(gè)接口容燕。Writable接口里有兩個(gè)方法,一個(gè)是write方法婚度,將對(duì)象寫入字節(jié)流蘸秘,另一個(gè)是readFields方法,從字節(jié)流解析出對(duì)象蝗茁。
Java的API提供了Comparable接口醋虏,也就是java.lang.Comparable接口。這個(gè)接口只有一個(gè)方法哮翘,就是compareTo颈嚼,用于比較兩個(gè)對(duì)象。
WritableComparable接口同時(shí)繼承了Writable和Comparable這兩個(gè)接口饭寺。
Hadoop里的三個(gè)類IntWritable阻课、DoubleWritable和ByteWritable,都繼承了WritableComparable接口艰匙。注意限煞,IntWritable、DoubleWritable和ByteWritable员凝,盡管后綴是“Writable”署驻,但它們不是接口,是類!硕舆!
以上是摘自大神博文秽荞。
下面是自己總結(jié)代碼?
代碼:package xlh;
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.util.StringUtils;
public class inser {
/**
* 序列化步驟
* 1.聲明一個(gè)靜態(tài)的類型時(shí)數(shù)組的函數(shù),并在里面?zhèn)鬟f參數(shù)抚官,而這個(gè)參數(shù)是Hadoop 里面InWritable 類的對(duì)象
* 2.使用Java.io包下的ByteArrayOutputStream 這個(gè)類并實(shí)例化扬跋,取名為out 即輸出對(duì)象,這里是從本地文件輸入到hdfs 上 還起到把結(jié)構(gòu)化數(shù)據(jù)轉(zhuǎn)化為字符流
* 3.使用Java.io包下的DataOutputStream 類并實(shí)例化凌节,取名為dataoutput ,這里參數(shù)是out
* 4.調(diào)用InWritable 類的對(duì)像的write(); 顧名思義钦听,要把本地文件寫到hdfs上
* 5.關(guān)閉數(shù)據(jù)流對(duì)象
* 6.返回值,返回out對(duì)象的toByteArray(); 這個(gè)含義倍奢,我也不是太清楚
*/
public static byte[] serialize(IntWritable intw) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
DataOutputStream dataoutput = new DataOutputStream(out);
intw.write(dataoutput);
dataoutput.close();
return out.toByteArray();
}
/**
* 反序列化步驟
* 1.聲明一個(gè)靜態(tài)的類型時(shí)數(shù)組的函數(shù)朴上,并在里面?zhèn)鬟f參數(shù),而這個(gè)參數(shù)是Hadoop 里面InWritable 類的對(duì)象
* 2.使用Java.io包下的ByteArrayOutputStream 這個(gè)類并實(shí)例化卒煞,取名為in,即輸入對(duì)象痪宰,這里是從hdfs 上文件輸入到 本地,還起到把結(jié)構(gòu)化數(shù)據(jù)轉(zhuǎn)化為字符流
* 3.使用Java.io包下的DataIutputStream 類并實(shí)例化畔裕,取名為datain ,這里參數(shù)是in
* 4.調(diào)用InWritable 類的對(duì)像的readFields(); 顧名思義衣撬,要把hdfs上文件寫到本地
* 5.關(guān)閉數(shù)據(jù)流對(duì)象
* 6.返回值
*/
public static byte[] deserialize(IntWritable intw2, byte[] bytes) throws IOException {
ByteArrayInputStream in = new ByteArrayInputStream(bytes);
DataInputStream datain = new DataInputStream(in);
intw2.readFields(datain);
datain.close();
return bytes;
}
/* 使用Hadoop中的intwritable 類并實(shí)例化
* 聲明數(shù)組,并把inwritable 類對(duì)象intw 當(dāng)做參數(shù)傳給serialize
* 開始執(zhí)行序列化
*
*
*
* 使用Hadoop中的intwritable 類并實(shí)例化
* 聲明數(shù)組扮饶,并把inwritable 類對(duì)象intw 當(dāng)做參數(shù)傳給serialize
* 開始執(zhí)行反序列化
*
*
* */
public static void main(String[] args) throws IOException {
IntWritable intw = new IntWritable();
byte[] bytes = serialize(intw);
String bytes_str = StringUtils.byteToHexString(bytes);
System.out.println(bytes_str);
IntWritable intw2 = new IntWritable(0);
deserialize(intw2, bytes);
System.out.println(intw2);
}
}
個(gè)人小體會(huì):
????????????? 今天敲這寫代碼給我的感覺具练,在此之前,我也看了關(guān)于序列化相關(guān)知識(shí)甜无,但都是一臉懵逼的看扛点,一臉懵逼的不懂!就是之前學(xué)習(xí)完全沒用過腦子岂丘,就是比葫蘆畫瓢陵究,現(xiàn)在慢慢的懂了,是時(shí)間的積累元潘,也是經(jīng)驗(yàn)的增加畔乙,也反映出,知識(shí)這東西需要經(jīng)常溫習(xí)翩概,需要體會(huì)牲距。說不定哪一天都頓悟了呢,只要堅(jiān)持去學(xué)習(xí)钥庇,或早或晚都會(huì)有收獲的牍鞠,慢慢的發(fā)現(xiàn),這個(gè)序列化就是套路评姨,Hadoop 支持三個(gè)序列化难述,IntWritable萤晴、DoubleWritable和ByteWritable
這里我只是找了其中一個(gè),如若工作需要胁后,根據(jù)需要自行調(diào)整店读。