隨筆 - 312, 文章 - 14, 評論 - 1393, 引用 - 0

          導航

          <2009年10月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          公告

          關注我的新浪微博

          我的著作









          常用鏈接

          留言簿(126)

          我參與的團隊

          隨筆分類(818)

          隨筆檔案(310)

          文章分類(1)

          文章檔案(8)

          相冊

          ADSL、3G查詢

          CSDN

          eclipse

          ibm

          Java EE

          Linux

          Web

          云服務

          代理網(wǎng)站

          關注的網(wǎng)站

          協(xié)議

          喜歡的Blog

          國內(nèi)廣告平臺

          圖書出版

          在線培訓

          開發(fā)工具

          微博客戶端

          手機鈴聲

          操作系統(tǒng)

          • ReactOS
          • 一個與windowXP/2003兼容的操作系統(tǒng)

          數(shù)學

          文件格式

          源碼資源

          移動(Mobile)

          編程語言

          英語學習

          最新隨筆

          搜索

          •  

          積分與排名

          • 積分 - 1974020
          • 排名 - 6

          最新評論

          閱讀排行榜

          評論排行榜

          Java網(wǎng)絡編程從入門到精通(34):讀寫緩沖區(qū)中的數(shù)據(jù)---使用get和put方法按順序讀寫單個數(shù)據(jù)

          本文為原創(chuàng),如需轉(zhuǎn)載,請注明作者和出處,謝謝!

          上一篇:Java網(wǎng)絡編程從入門到精通(33):非阻塞I/O的緩沖區(qū)(Buffer)

              對于緩沖區(qū)來說,最重要的操作就是讀寫操作。緩沖區(qū)提供了兩種方法來讀寫緩沖區(qū)中的數(shù)據(jù):getput方法和array方法。而getput方法可以有三種讀寫數(shù)據(jù)的方式:按順序讀寫單個數(shù)據(jù)、在指定位置讀寫單個數(shù)據(jù)和讀寫數(shù)據(jù)塊。除了上述的幾種讀寫數(shù)據(jù)的方法外,CharBuffer類還提供了用于專門寫字符串的putappend方法。在本文及后面的文章中將分別介紹這些讀寫緩沖區(qū)的方法。

          雖然使用allocate方法創(chuàng)建的緩沖區(qū)并不是一次性地分配內(nèi)存空間,但我們可以從用戶地角度將一個緩沖區(qū)想象成一個長度為capacity的數(shù)組。當緩沖區(qū)創(chuàng)建后,和數(shù)組一樣,緩沖區(qū)的大小(capacity值)將無法改變,也無法訪問緩沖區(qū)外的數(shù)據(jù)。如下面的代碼創(chuàng)建了一個大小為6的字節(jié)緩沖區(qū)。

          ByteBuffer byteBuffer = ByteBuffer.allocate(6);

          對于byteBuffer來說,只能訪問屬于這個緩沖區(qū)的六個字節(jié)的數(shù)據(jù),如果超過了這個范圍,將拋出一個BufferOverflowException異常,這是一個運行時錯誤,因為這個錯誤只能在程序運行時被發(fā)現(xiàn)。

          既然緩沖區(qū)和數(shù)組類似,那么緩沖區(qū)也應該象數(shù)組一樣可以標識當前的位置。緩沖區(qū)的position方法為我們提供了這個功能。position方法有兩種重載形式,它們的定義如下:

          public final int position()
          public final Buffer position(int newPosition)

          第一個重載形式用來獲取緩沖區(qū)的當前位置。在創(chuàng)建緩沖區(qū)后,position的初始值是0,也就是緩沖區(qū)第一個元素的位置。當從緩沖區(qū)讀取一個元素后,position的值加1。我們從這一點可以看出,position方法返回的位置就是當前可以讀取的元素的位置。position的取值范圍從0capacity – 1。如果position的值等于capacity,說明緩沖區(qū)當前已經(jīng)沒有數(shù)據(jù)可讀了。

          position方法的第二個重載形式可以設置緩沖區(qū)的當前位置。參數(shù)newPosition的取值范圍是0 <= newPosition < capacity。如果newPosition的值超出這個范圍,position方法就會拋出一個IllegalArgumentException異常。

          在大多數(shù)情況下不需要直接控制緩沖區(qū)的位置。緩沖區(qū)類提供的用于讀寫數(shù)據(jù)的方法可以自動地設置緩沖區(qū)的當前位置。在緩沖區(qū)類中,getput方法用于讀寫緩沖區(qū)中的數(shù)據(jù)。getput方法的定義如下:

          ByteBuffer類的getput方法:

          public abstract byte get()            
          public abstract ByteBuffer put(byte b)

          IntBuffer類的getput方法:

          public abstract int get()            
          public abstract IntBuffer put(int i)

          其他五個緩沖區(qū)類中的getput方法定義和上面的定義類似,只是get方法返回相應的數(shù)據(jù)類型,而put方法的參數(shù)是相應的數(shù)據(jù)類型,并且返回值的類型是相應的緩沖區(qū)類。

          每當put方法向緩沖區(qū)寫入一個數(shù)據(jù)后,緩沖區(qū)的當前位置都會加1。如果緩沖區(qū)的當前位置已經(jīng)等于capacity,調(diào)用put方法就會拋出一個java.nio.BufferOverflowException異常。在緩沖區(qū)未初賦值的區(qū)域?qū)⒈?/span>0填充。使用get方法可以得到緩沖區(qū)當前位置的數(shù)據(jù),并使緩沖區(qū)的當前位置加1。和put方法一樣,在緩沖區(qū)當前位置等于capacity時使用get方法也會拋出java.nio.BufferOverflowException異常。緩沖區(qū)的初始狀態(tài)如圖1所示。

          圖1 緩沖區(qū)的初始狀態(tài)

          從圖1可以看出,在緩沖區(qū)創(chuàng)建之初,當前的位置和緩沖區(qū)中的數(shù)據(jù)都為0。當使用如下語句向緩沖區(qū)中寫入數(shù)據(jù)后,緩沖區(qū)當前狀態(tài)如圖2所示。

           

          byteBuffer.put((byte)2);
          byteBuffer.put((
          byte)-1);

          圖2  緩沖區(qū)的當前狀態(tài)

           

          當緩沖區(qū)的當前位置如圖3所示時,使用putget方法將會拋出上述的BufferOverflowException異常。

          圖3  當前位置處于緩沖區(qū)尾

          如果要使用get方法得到緩沖區(qū)中的指定數(shù)據(jù),必須將緩沖區(qū)的當前位置移動到指定的位置,我們可以使用position方法將當前位置移到緩沖區(qū)的任何位置。如下面的代碼將圖3所示的緩沖區(qū)的當前位置設為2,并用get方法獲得位置2的數(shù)據(jù):

          byteBuffer.position(2);
          System.out.println(byteBuffer.get());

          上面的代碼將輸出3。緩沖區(qū)的當前位置為除了使用position方法,也可以使用rewind方法將緩沖區(qū)的當前位置設為0rewind方法的定義如下:

          public final Buffer rewind()

          在圖2所示的緩沖區(qū)狀態(tài)下調(diào)用rewind方法,就會得到如圖4的緩沖區(qū)狀態(tài)。

          圖4  調(diào)用rewind方法后的緩沖區(qū)狀態(tài)

          接下來讓我們執(zhí)行如下語句:

          System.out.println(byteBuffer.get());

          緩沖區(qū)的狀態(tài)將如圖5所示。

          圖5  調(diào)用get方法后的緩沖區(qū)狀態(tài)

          緩沖區(qū)除了positioncapacity外,還提供了一個標識來限制緩沖區(qū)可訪問的范圍。這個標識就是limitlimitposition一樣,在緩沖區(qū)類中也提供了兩個重載方法。用于獲得和設置limit的值。limit方法的定義如下:


          public final int limit()
          public final Buffer limit(int newLimit)

          在初始狀態(tài)下,緩沖區(qū)的limitcapacity值相同。但limitcapacity的區(qū)別是limit可以通過limit方法進行設置,而capacity在創(chuàng)建緩沖區(qū)時就已經(jīng)指定了,并且不能改變。(在上面所講的position方法的newPosition參數(shù)的取值范圍時曾說是0 <= newPosition < capacity,其實嚴格地說,應是0 <= newPosition < limitlimit的其他性質(zhì)和capacity一樣。如在圖5所示的緩沖區(qū)狀態(tài)中將limit的值設為2,就變成了圖6所示的狀態(tài)。

          圖6  將limit設為2的緩沖區(qū)狀態(tài)

          在這時position的值等于limit,就不能訪問緩沖區(qū)的當前數(shù)據(jù),也就是說不能使用getput方法。否則將拋出BufferOverflowException異常。由于使用allocate創(chuàng)建的緩沖區(qū)并不是一次性地分配內(nèi)存空間,因此,可以將緩沖區(qū)的capacity設為很大的值,如10M。緩沖區(qū)過大可能在某些環(huán)境中會使系統(tǒng)性能降低(如在PDA或智能插秧機中),因此,可以使用limit方法根據(jù)具體的情況來限定緩沖區(qū)的大小。當然,limit還可以表示緩沖區(qū)中實際的數(shù)據(jù)量,這將在后面講解。下面的代碼演示了如何使用limit方法來枚舉緩沖區(qū)中的數(shù)據(jù):

          while(byteBuffer.position() < byteBuffer.limit())
              System.out.println(byteBuffer.get());

          我們還可以用fliphasRemaining方法來重寫上面的代碼。flip方法將limit設為緩沖區(qū)的當前位置。當limit等于position時,hasRemaining方法返回false,而則返回true fliphasRemaining方法的定義如下:


          public final Buffer flip()
          public final boolean hasRemaining()

              下面的代碼演示了如何使用hasRemaining方法來枚舉緩沖區(qū)中的數(shù)據(jù):

          while(byteBuffer.hasRemaining())
              System.out.println(byteBuffer.get());

          如果從緩沖區(qū)的第一個位置依次使用put方法向緩沖區(qū)寫數(shù)據(jù),當寫完數(shù)據(jù)后,再使用flip方法。這樣limit的值就等于緩沖區(qū)中實際的數(shù)據(jù)量了。在網(wǎng)絡中傳遞數(shù)據(jù)時,可以使用這種方法來設置數(shù)據(jù)的結束位置。

          為了回顧上面所講內(nèi)容,下面的代碼總結了創(chuàng)建緩沖區(qū)、讀寫緩沖區(qū)中的數(shù)據(jù)、設置緩沖區(qū)的limitposition的方法。

            package net;
            
            
          import java.nio.*;
            
            
          public class GetPutData
            {
                
          public static void main(String[] args)
                {
                    
          // 創(chuàng)建緩沖區(qū)的四種方式
                    IntBuffer intBuffer = IntBuffer.allocate(10);
                    ByteBuffer byteBuffer 
          = ByteBuffer.allocateDirect(10);
                    CharBuffer charBuffer 
          = CharBuffer.wrap("abcdefg");
                    DoubleBuffer doubleBuffer 
          = DoubleBuffer.wrap(new double[] { 1.12.2 });
                    
                    
          // 向緩沖區(qū)中寫入數(shù)據(jù)
                    intBuffer.put(1000);
                    intBuffer.put(
          2000);
                    
                    System.out.println(
          "intBuffer的當前位置:" + intBuffer.position());
                    
                    intBuffer.position(
          1);  // 將緩沖區(qū)的當前位置設為1
                    System.out.println(intBuffer.get());  // 輸出緩沖區(qū)的當前數(shù)據(jù)
                    
                    intBuffer.rewind();  
          // 將緩沖區(qū)的當前位置設為0
                    System.out.println(intBuffer.get());  // 輸出緩沖區(qū)的當前數(shù)據(jù)
                    
                    byteBuffer.put((
          byte)20);
                    byteBuffer.put((
          byte)33);
                    byteBuffer.flip();   
          // 將limit設為position,在這里是2
                    byteBuffer.rewind(); 
                    
          while(byteBuffer.hasRemaining())  // 枚舉byteBuffer中的數(shù)據(jù)
                        System.out.print(byteBuffer.get() + " ");
                    
                    
          while(charBuffer.hasRemaining())  // 枚舉charBuffer中的數(shù)據(jù)
                        System.out.print(charBuffer.get() + " ");
            
                    
          // 枚舉doubleBuffer中的數(shù)據(jù)
                    while(doubleBuffer.position() < doubleBuffer.limit())
                        System.out.print(doubleBuffer.get() 
          + " ");
            
                }
            }

          運行結果:  

          intBuffer的當前位置:2
          2000
          1000
          20 33 a b c d e f g 1.1 2.2

          注意:如果必須使用緩沖區(qū)的大小來讀取緩沖區(qū)的數(shù)據(jù),盡量不要使用capacity,而要使用limit。如盡量不要寫成如下的代碼:

          while(byteBuffer.position() < byteBuffer.capacity())
              System.out.println(byteBuffer.get());

          這是因為當limit比capacity小時,上面的代碼將會拋出一個BufferUnderflowException異常。





          Android開發(fā)完全講義(第2版)(本書版權已輸出到臺灣)

          http://product.dangdang.com/product.aspx?product_id=22741502



          Android高薪之路:Android程序員面試寶典 http://book.360buy.com/10970314.html


          新浪微博:http://t.sina.com.cn/androidguy   昵稱:李寧_Lining

          posted on 2009-10-09 09:34 銀河使者 閱讀(4882) 評論(1)  編輯  收藏 所屬分類: java 原創(chuàng)網(wǎng)絡編程

          評論

          # re: Java網(wǎng)絡編程從入門到精通(34):讀寫緩沖區(qū)中的數(shù)據(jù)---使用get和put方法按順序讀寫單個數(shù)據(jù)  回復  更多評論   

          講的真不錯,不知道有沒有的更新了
          2010-06-05 20:07 | 菜鳥學習
          主站蜘蛛池模板: 深水埗区| 晋江市| 卓尼县| 莱西市| 永泰县| 内丘县| 息烽县| 辛集市| 隆回县| 汽车| 宁化县| 新安县| 镇安县| 乐亭县| 拜泉县| 平度市| 全南县| 曲阜市| 墨玉县| 海原县| 左云县| 葵青区| 仁怀市| 曲阜市| 宜黄县| 安国市| 崇左市| 全椒县| 高清| 梁平县| 新巴尔虎左旗| 铅山县| 高尔夫| 鹤山市| 霍林郭勒市| 垣曲县| 宝山区| 延津县| 清水县| 牡丹江市| 资中县|