1. 程式人生 > >Hadoop Serialization -- hadoop序列化詳解 (2)【Text,BytesWritable,NullWritable】

Hadoop Serialization -- hadoop序列化詳解 (2)【Text,BytesWritable,NullWritable】

回顧: 回顧序列化,其實原書的結構很清晰,我截圖給出書中的章節結構: 序列化最主要的,最底層的是實現writable介面,wiritable規定讀和寫的遊戲規則 (void write(DataOutput out) throws IOException;  void readFields(DataInput in) throws IOException;)。為了適應hadoop的mapreduce的運算特性,也就是map 和reduce對key的比較,排序的功能,就要實現Comparable介面,這個介面規定 public int compareTo(T o);這個方法。為了增強處理大資料集的能力,我們不能老是先序列化,傳輸,反序列化,然後進行比較compare,太消耗時間和效能了,我們有了增強的RawComparator,RawComparator是Comparator的增強版,可以比較沒有被反序列化的資料。
hadoop需要處理的資料五花八門,java具有的基本資料型別都有可能在hadoop中出現,hadoop因此包裝了java的基本資料型別使他們實現以上的介面並且給予實現細節。這些類都實現了WritableComparable介面,插上飛翔的翅膀,可以在不同的hadoop節點之間毫無障礙的傳輸了,如入無人之境。 既然Text拿出來單獨討論。自然就要好好研究一下Text的實現細節,對於我們對hadoop的設計細節和思想太重要太重要。 Text是UTF-8字串的Writable實現。被看做是java String型別的替換。Text 類代替了UTF8 類, UTF8 類不支援編碼大於32767 個位元組的字元.使用了Java 改進過的UTF-8.
Text 使用int 型(使用一個可變長度的編碼方案)在字元感編碼中儲存位元組數. 最大值是2 GB 。此外, Text 使用標準的UTF芯,使其更易於與理解U T F-8 的其他工具協同工作.
為什麼是2GB,我估計很少人會思考這個問題,我們簡單計算一下: 利用int儲存位元組長度,int最大是2^31-1,那麼位元組最大長度就是2^31-1 Text能夠容納的大小R=(2^31-1)/1024/1024/1024=1.99999999=2GB 因此我們使用他的時候要知道他的大小是有限制的。 由於強調使用標準的UTF8,所以Text 和Java 的String 類之間還是有一些區別的。Text 類的索引位於編碼後的位元組系列中,而不是字串中的
Unicode 字元.或Java 的char 編碼單元{如同String 一樣)。舉例如下:
這方面的差異用中文就很好的說明這個問題。  String line = "滾滾長江東逝水";     System.out.println(line.length());     Text text = new Text(line);     System.out.println(text.getLength());     System.out.println(line.charAt(2));     System.out.println(text.charAt(2)); 輸出: 7 21
-1     String line = "merry christmas";     System.out.println(line.length());     Text text = new Text(line);     System.out.println(text.getLength());     System.out.println(line.charAt(2));     System.out.println(text.charAt(2)); 輸出: 15 15 r 114 可以看出來,他們的索引(Index)是真的不一樣,同一個索引值取出來的並不是同一個東西。 注意, charAt ( )返回了一個int 型別來表示Unicode 程式碼點, 而不是像String 變量那樣返回一個char 型別。在開始使用一個以上位元組進行編碼的字元(例如中文!!), Text 和String 之間的區別是很明顯的。下表展示了Unicode的程式碼點。 U+0041 程式碼點對應大寫字母A 一直到U+00DFUTF-8都是一個位元組編碼,剩下的都是兩個位元組以上。而對於java,最後一行,只有最後一個程式碼點是兩個,其他的都是一個位元組的。這點差別很大。 怕很多人不懂程式碼點,我再解釋一下: Unicode 是通用字元編碼標準,用於表示文字以供計算機處理。Unicode 提供了一種對多語種文字進行一致編碼的方法,便於國際文字檔案的交換。每個 Unicode 字元均對映到一個程式碼點,程式碼點是一個介於 0 和 1,114,111 之間的整數。Unicode 程式碼點使用 U+nnnn 形式的表示法來表示(其中 nnnn 是程式碼點的十六進位制數),或使用描述程式碼點的文字字串來表示。例如,小寫字母 “a” 可以用 U+0061 或文字字串 "LATIN SMALL LETTER A" 來表示。 程式碼點可以使用不同的字元編碼方案進行編碼。在 Oracle Solaris Unicode 語言環境中,使用的是 UTF-8 形式。UTF-8 是 Unicode 的一種可變長度編碼形式,它透明地保留了 ASCII 字元程式碼值(請參見UTF-8 概述)。 程式碼點就是一個字元在Unicode中對應的編碼。 String 的長度是它包括的字元個數 ,但Text 物件的長度是其UTF -8 編碼的位元組數. 同樣, indexOf () 方泣返回一個char 型別的編碼單元的索引,find () 方格是位元組偏移量.請看例子: @Test public void string() throws UnsupportedEncodingException { String s = "\u0041\u00DF\u6771\uD801\uDC00"; assertThat(s.length(), is(5)); assertThat(s.getBytes("UTF-8").length, is(10)); assertThat(s.indexOf("\u0041"), is(0)); assertThat(s.indexOf("\u00DF"), is(1)); assertThat(s.indexOf("\u6771"), is(2)); assertThat(s.indexOf("\uD801\uDC00"), is(3)); assertThat(s.charAt(0), is('\u0041')); assertThat(s.charAt(1), is('\u00DF')); assertThat(s.charAt(2), is('\u6771')); assertThat(s.charAt(3), is('\uD801')); assertThat(s.charAt(4), is('\uDC00')); assertThat(s.codePointAt(0), is(0x0041)); assertThat(s.codePointAt(1), is(0x00DF)); assertThat(s.codePointAt(2), is(0x6771)); assertThat(s.codePointAt(3), is(0x10400)); } @Test public void text() { Text t = new Text("\u0041\u00DF\u6771\uD801\uDC00"); assertThat(t.getLength(), is(10));   //10 = 1+2+3+4 是其UTF -8 編碼的位元組數   assertThat(t.find("\u0041"), is(0)); assertThat(t.find("\u00DF"), is(1)); assertThat(t.find("\u6771"), is(3)); assertThat(t.find("\uD801\uDC00"), is(6)); assertThat(t.charAt(0), is(0x0041)); assertThat(t.charAt(1), is(0x00DF)); assertThat(t.charAt(3), is(0x6771)); assertThat(t.charAt(6), is(0x10400)); } 遍歷Text,迭代 迭代使用索引的位元組偏移對Text 中的Unicode 字元進行途代是很複雜的,因為你不能只增加索引。迭代的定義有點模糊(見例4-6 ) 將Text 物件變成java.nio.ByteBuffer然後對緩衝的Text 反覆呼叫bytesToCodePoint() 靜態方法.這個方泣提取下一個程式碼點作為int 然後更新緩衝中的位置。當bytesToCodePoint() 返回- 1 時,檢測到字元結束。意思就是說,我們取字元的時候,是一整個一整個字元的取,我們不能夠按照索引來取,我們按照程式碼點整個整個的取。 public class TextIterator { 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) {     System.out.println(Integer.toHexString(cp)); } } } 輸出: 41 df 6771 10400 可修改性 String 和Text 的另一個區別在於可修改性(像Hadoop 中的所有Writable 實視一樣,但NullWritable 除外,後者是單例項物件)。我們可以通過對它呼叫set() 函式來重用Text 例項。示例如下: Text t = new Text("hadoop"); t.set("pig"); assertThat(t.getLength(), is(3)); assertThat(t.getBytes().length, is(3)); 轉為字串 Text 不像java. l ang.String 一樣有一個可以處理字串的API ,所以在許多情況下,需要將Text 物件轉化為String 物件。這通常用toString()方法來完成。 assertThat(new Text("hadoop ") . toString() , is( "hadoop")); BytesWritable BytesWritable 是一個二進位制資料陣列封裝。它的序列化格式是一個int 欄位(4位元組) ,指定的是位元組數及位元組本身。例如, 一個長度為2 ,值為3 和5 的位元組數組序列化為一個4 位元組的整數(00000002)加上兩個來自陣列的位元組(03 和05) 。 BytesWritable b = new BytesWritable(new byte[] { 3, 5 }); byte[] bytes = serialize(b); assertThat(StringUtils.byteToHexString(bytes), is("000000020305")); BytesWritab1e 是可變的,其值可通過呼叫set ( )方撞來改變。和Text一樣 ,從getBytes ( )方法返回的位元組陣列大小可能並沒有反映出儲存在BytesWritable 的資料的實際大小.可以通過呼叫getLength () 方法來確定BytesWritable 的長度,例如: b.setCapacity(11); assertThat(b.getLength(), is(2)); assertThat(b.getBytes().length, is(11)); NullWritable NullWritable 是一種特殊的Writable 型別,因為它的序列化是零長度的。沒有位元組被寫入流或從流中讀出.它被用作佔位符.例如,在MapReduce 中,在不需要這個位置的時候,鍵或值可以被宣告為NullWritable,他有效儲存了一個不變的空值。NullWritable 也可以很有用,在打算儲存一系列值的時候,作為SequenceFile 的一個鍵,而不是鍵/值對。它是一個不變的單例項,其例項可以通過呼叫NullWritable.get() 方法來檢索。 今天就到這裡。 Charles 2015-12-24晚於P.P 版權說明: 本文由Charles Dong原創,本人支援開源以及免費有益的傳播,反對商業化謀利。 CSDN部落格:http://blog.csdn.net/mrcharles 個人站:http://blog.xingbod.cn EMAIL:[email protected]

相關推薦

Hadoop Serialization -- hadoop序列 (2)Text,BytesWritable,NullWritable

回顧: 回顧序列化,其實原書的結構很清晰,我截圖給出書中的章節結構: 序列化最主要的,最底層的是實現writable介面,wiritable規定讀和寫的遊戲規則 (void write(DataOu

Hadoop Serialization -- hadoop序列具體解釋 (2)Text,BytesWritable,NullWritable

tao small oid rem cef get() 每一個 包含 協同工作 回想: 回想序列化,事實上原書的結構非常清晰,我截圖給出書中的章節結構: 序列化最基本的,最底層的是實現writable接口,wiritable規定讀和寫的遊戲規則 (void

Java物件的序列Serialization)和反序列

1.序列化和反序列化 序列化(Serialization)是將物件的狀態資訊轉化為可以儲存或者傳輸的形式的過程,一般將一個物件儲存到一個儲存媒介,例如檔案或記憶體緩衝等,在網路傳輸過程中,可以是位元組或者XML等格式;而位元組或者XML格式的可以還原成完全相等

java 物件的序列

序列化 物件序列化的目標是將物件儲存到磁碟中,或者允許在網路中直接傳輸物件。物件序列化機制允許把記憶體中的JAVA物件轉換成跟平臺無關的二進位制流,從而允許將這種二進位制流持久地儲存在磁碟上,通過網路將這種二進位制流傳輸到另一個網路節點,其他程式一旦獲得了這種二進位制流,都可以講二進位制流恢復成

物件序列

前言 我們在做web專案的時候,在網路傳輸中,序列化是繞不過去的重要一環。今天就來總結一下序列化到底能為我們做些什麼 概念 序列化機制:允許把記憶體中的Java物件轉換成平臺無關的二進

Hessian序列

簡單示例 com.spy.test.hessian.User public class User implements Serializable { private Long user

java 序列和反序列

1、什麼是序列化?為什麼要序列化? Java 序列化就是指將物件轉換為位元組序列的過程,而反序列化則是隻將位元組序列轉換成目標物件的過程。 我們都知道,在進行瀏覽器訪問的時候,我們看到的文字、圖片、音訊、視訊等都是通過二進位制序列進行傳輸的,那麼如果我們需要將Java

Java序列

啟用 協議 pri edi ado class 反序 標記 自動 轉載請註明原文地址:https://www.cnblogs.com/ygj0930/p/10857597.html 一:什麽是序列化與反序列化   序列化:對象序列化是指將Java對象(動態的

hadoop中的序列

此文已由作者肖凡授權網易雲社群釋出。 歡迎訪問網易雲社群,瞭解更多網易技術產品運營經驗。 最近在學習hadoop,發現hadoop的序列化過程和jdk的序列化有很大的區別,下面就來說說這兩者的區別都有哪些。 1、先簡單回顧下JAVA的序列化 JDK的序列化只要實現serializ

hadoop環境安裝配置步驟

hadoop環境安裝配置步驟詳解 在上一篇的分享文章中我是給大家分享了執行部署hadoop的一些安裝準備工作,這篇接上一篇繼續為大家分享一些個人的學習經驗總結。我學習用的是大快發行版DKHadoop,所以所有的經驗分享都是以DKHadoop為基礎,這裡要先說明一下。個人覺得DKHadoop對

Hadoop Mapreduce的shuffle過程

1、map task讀取資料時預設呼叫TextInputFormat的成員RecoreReader,RecoreReader呼叫自己的read()方法,進行逐行讀取,返回一個key、value; 2、返回的key、value交給自定義的map方法,輸出的context.write(key,value),再交

hadoop的資料序列型別

hadoop的資料序列化型別         IntWritable,FloatWritable,LongWritable,DoubleWritable,Text,         

Hadoop hadoop yarn 指令相關引數

[Plain Text] 純文字檢視 複製程式碼 ? 1 2 [[email protected] bin]$ yarn classpath /home/hadoop/apache/hadoop-2.4.1/etc/hadoop:

Hadoop--倒排索引過程

倒排索引就是根據單詞內容來查詢文件的方式,由於不是根據文件來確定文件所包含的內容,進行了相反的操作,所以被稱為倒排索引 下面來看一個例子來理解什麼是倒排索引 這裡我準備了兩個檔案 分別為1.txt和2.txt 1.txt的內容如下 I Lo

Hadoop - HDFS - MapReduce - YARN - HA

Hadoop 為什麼要有Hadoop?       從計算機誕生到現今,積累了海量的資料,這些海量的資料有結構化、半結構化、非 結構的資料,並且這些海量的資料儲存和檢索就成為了一大問題。     

Hadoop之本地執行模式

Hadoop的執行模式分為3種:本地執行模式,偽分佈執行模式,叢集執行模式,相應概念如下:  1、獨立模式即本地執行模式(standalone或local mode)  無需執行任何守護程序(daemon),所有程式都在單個JVM上執行。由於在本機模式下測試和

Hadoop分散式檔案系統——HDFS

這篇主要聊一下Hadoop分散式檔案系統—HDFS 大綱: 1.HDFS設計目標 2.HDFS裡面的NameNode和DataNode 3.操作HDFS的兩種方式 1.HDFS設計目標 硬體錯誤 硬體錯誤是常態而不是異常。(每每讀這句我就想到了:程式設計師加

WebStorm2018.1.5安裝破解及漢 適用於WebStorm2018.2

1,軟體下載       1,官方網站下載:HTTPS://www.jetbrains.com/webstorm/       2,百度雲盤下載(WebStorm-2018年1月5日)https://pan.baidu.com/s/1QAMCtyoqbcapzOqPaaY

Hadoop核心架構內部機理

HDFS的體系架構 整個Hadoop的體系結構主要是通過HDFS來實現對分散式儲存的底層支援,並通過MR來實現對分散式並行任務處理的程式支援。 HDFS採用主從(Master/Slave)結構模型,一個HDFS叢集是由一個NameNode和若干個DataNode組成的

3.hadoop中的序列

序列化的三種主要途徑 作為一種序列化格式:一個物件序列化以後,它的編碼可以被儲存到磁碟上,供以後反序列化使用 作為一種通訊資料格式:序列化結果可以從一個正在執行的虛擬機器,通過網路被傳遞到另一個虛