熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

讀寫緩沖區中的數據

2013-11-23 18:56:41  來源: Java核心技術 

  對於緩沖區來說最重要的操作就是讀寫操作緩沖區提供了兩種方法來讀寫緩沖區中的數據getput方法和array方法而getput方法可以有三種讀寫數據的方式按順序讀寫單個數據在指定位置讀寫單個數據和讀寫數據塊除了上述的幾種讀寫數據的方法外CharBuffer類還提供了用於專門寫字符串的put和append方法在本文及後面的文章中將分別介紹這些讀寫緩沖區的方法
   
    雖然使用allocate方法創建的緩沖區並不是一次性地分配內存空間但我們可以從用戶地角度將一個緩沖區想象成一個長度為capacity的數組當緩沖區創建後和數組一樣緩沖區的大小(capacity值)將無法改變也無法訪問緩沖區外的數據如下面的代碼創建了一個大小為的字節緩沖區
   
    ByteBuffer byteBuffer = ByteBufferallocate(
   
    對於byteBuffer來說只能訪問屬於這個緩沖區的六個字節的數據如果超過了這個范圍將拋出一個BufferOverflowException異常這是一個運行時錯誤因為這個錯誤只能在程序運行時被發現
   
    既然緩沖區和數組類似那麼緩沖區也應該象數組一樣可以標識當前的位置緩沖區的position方法為我們提供了這個功能position方法有兩種重載形式它們的定義如下
   
    public final int position()
   
    public final Buffer position(int newPosition)
   
    第一個重載形式用來獲取緩沖區的當前位置在創建緩沖區後position的初始值是也就是緩沖區第一個元素的位置當從緩沖區讀取一個元素後position的值加我們從這一點可以看出position方法返回的位置就是當前可以讀取的元素的位置position的取值范圍從到capacity – 如果position的值等於capacity說明緩沖區當前已經沒有數據可讀了
   
    position方法的第二個重載形式可以設置緩沖區的當前位置參數newPosition的取值范圍是 <= newPosition < capacity如果newPosition的值超出這個范圍position方法就會拋出一個IllegalArgumentException異常
   
    在大多數情況下不需要直接控制緩沖區的位置緩沖區類提供的用於讀寫數據的方法可以自動地設置緩沖區的當前位置在緩沖區類中get和put方法用於讀寫緩沖區中的數據get和put方法的定義如下
   
    ByteBuffer類的get和put方法
   
    public abstract byte get()
   
    public abstract ByteBuffer put(byte b)
   
    IntBuffer類的get和put方法
   
    public abstract int get()
   
    public abstract IntBuffer put(int i)
   
    其他五個緩沖區類中的get和put方法定義和上面的定義類似只是get方法返回相應的數據類型而put方法的參數是相應的數據類型並且返回值的類型是相應的緩沖區類
   
    每當put方法向緩沖區寫入一個數據後緩沖區的當前位置都會加如果緩沖區的當前位置已經等於capacity調用put方法就會拋出一個javanioBufferOverflowException異常在緩沖區未初賦值的區域將被填充使用get方法可以得到緩沖區當前位置的數據並使緩沖區的當前位置加和put方法一樣在緩沖區當前位置等於capacity時使用get方法也會拋出javanioBufferOverflowException異常緩沖區的初始狀態如圖所示

   
 圖 緩沖區的初始狀態

  從圖可以看出在緩沖區創建之初當前的位置和緩沖區中的數據都為當使用如下語句向緩沖區中寫入數據後緩沖區當前狀態如圖所示
   
    byteBufferput((byte)
   
    byteBufferput((byte)

   
  緩沖區的當前狀態

  當緩沖區的當前位置如圖所示時使用put和get方法將會拋出上述的BufferOverflowException異常

   
  當前位置處於緩沖區尾

  


    如果要使用get方法得到緩沖區中的指定數據必須將緩沖區的當前位置移動到指定的位置我們可以使用position方法將當前位置移到緩沖區的任何位置如下面的代碼將圖所示的緩沖區的當前位置設為並用get方法獲得位置的數據
   
    byteBufferposition(
   
    Systemoutprintln(byteBufferget())
   
    上面的代碼將輸出緩沖區的當前位置為除了使用position方法也可以使用rewind方法將緩沖區的當前位置設為rewind方法的定義如下
   
    public final Buffer rewind()
   
    在圖所示的緩沖區狀態下調用rewind方法就會得到如圖的緩沖區狀態

   
  調用rewind方法後的緩沖區狀態

  接下來讓我們執行如下語句
   
    Systemoutprintln(byteBufferget())
   
    緩沖區的狀態將如圖所示

   
  調用get方法後的緩沖區狀態

  緩沖區除了position和capacity外還提供了一個標識來限制緩沖區可訪問的范圍這個標識就是limitlimit和position一樣在緩沖區類中也提供了兩個重載方法用於獲得和設置limit的值limit方法的定義如下
   
    public final int limit()
   
    public final Buffer limit(int newLimit)
   
    在初始狀態下緩沖區的limit和capacity值相同但limit和capacity的區別是limit可以通過limit方法進行設置而capacity在創建緩沖區時就已經指定了並且不能改變(在上面所講的position方法的newPosition參數的取值范圍時曾說是 <= newPosition < capacity其實嚴格地說應是 <= newPosition < limit)limit的其他性質和capacity一樣如在圖所示的緩沖區狀態中將limit的值設為就變成了圖所示的狀態

   
  將limit設為的緩沖區狀態

  在這時position的值等於limit就不能訪問緩沖區的當前數據也就是說不能使用get和put方法否則將拋出BufferOverflowException異常由於使用allocate創建的緩沖區並不是一次性地分配內存空間因此可以將緩沖區的capacity設為很大的值M緩沖區過大可能在某些環境中會使系統性能降低(如在PDA或智能插秧機中)因此可以使用limit方法根據具體的情況來限定緩沖區的大小當然limit還可以表示緩沖區中實際的數據量這將在後面講解下面的代碼演示了如何使用limit方法來枚舉緩沖區中的數據
   
    while(byteBufferposition() < byteBufferlimit())
   
    Systemoutprintln(byteBufferget())
   


    我們還可以用flip和hasRemaining方法來重寫上面的代碼flip方法將limit設為緩沖區的當前位置當limit等於position時hasRemaining方法返回false而則返回true flip和hasRemaining方法的定義如下
   
    public final Buffer flip()
   
    public final boolean hasRemaining()
   
    下面的代碼演示了如何使用hasRemaining方法來枚舉緩沖區中的數據
   
    while(byteBufferhasRemaining())
   
    Systemoutprintln(byteBufferget())
   
    如果從緩沖區的第一個位置依次使用put方法向緩沖區寫數據當寫完數據後再使用flip方法這樣limit的值就等於緩沖區中實際的數據量了在網絡中傳遞數據時可以使用這種方法來設置數據的結束位置
   
    為了回顧上面所講內容下面的代碼總結了創建緩沖區讀寫緩沖區中的數據設置緩沖區的limit和position的方法
   
    package net;
   
    import javanio*;
   
    public class GetPutData
   
    {
   
    public static void main(String[] args)
   
    {
   
    // 創建緩沖區的四種方式
   
    IntBuffer intBuffer = IntBufferallocate(
   
    ByteBuffer byteBuffer = ByteBufferallocateDirect(
   
    CharBuffer charBuffer = CharBufferwrap(abcdefg
   
    DoubleBuffer doubleBuffer = DoubleBufferwrap(new double[] { })
   
    // 向緩沖區中寫入數據
   
    intBufferput(
   
    intBufferput(
   
    Systemoutprintln(intBuffer的當前位置 + intBufferposition())
   
    intBufferposition(  // 將緩沖區的當前位置設為
   
    Systemoutprintln(intBufferget())  // 輸出緩沖區的當前數據
   
    intBufferrewind()  // 將緩沖區的當前位置設為
   
    Systemoutprintln(intBufferget())  // 輸出緩沖區的當前數據
   
    byteBufferput((byte)
   
    byteBufferput((byte)
   
    byteBufferflip()   // 將limit設為position在這裡是
   
    byteBufferrewind()
   
    while(byteBufferhasRemaining())  // 枚舉byteBuffer中的數據
   
    Systemoutprint(byteBufferget() +
   
    while(charBufferhasRemaining())  // 枚舉charBuffer中的數據
   
    Systemoutprint(charBufferget() +
   
    // 枚舉doubleBuffer中的數據
   
    while(doubleBufferposition() < doubleBufferlimit())
   
    Systemoutprint(doubleBufferget() +
   
    }
   
    }
   
    運行結果
   
    intBuffer的當前位置
   
   
   
   
   
    a b c d e f g
   
    注意如果必須使用緩沖區的大小來讀取緩沖區的數據盡量不要使用capacity而要使用limit如盡量不要寫成如下的代碼
   
    while(byteBufferposition() < byteBuffercapacity())
   
    Systemoutprintln(byteBufferget())
   
    這是因為當limit比capacity小時上面的代碼將會拋出一個BufferUnderflowException異常


From:http://tw.wingwit.com/Article/program/Java/hx/201311/26014.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.