Java緩衝區讀寫

緩衝區讀

有兩種方法從緩衝區讀取數據:

  • 絕對位置
  • 相對位置

使用四個版本重載的get()方法用於從緩衝區讀取數據。

  • get(int index)返回給定索引處的數據。

  • get()從緩衝區中的當前位置返回數據,並將位置增加1

  • get(byte [] destination,int offset,int length)從緩衝區中批量讀取數據。 它從緩衝區的當前位置讀取長度字節數,並將它們放在從指定偏移量開始的指定目標數組中。

  • get(byte [] destination)通過從緩衝區的當前位置讀取數據並且每次讀取數據元素時將當前位置遞增1來填充指定的目標數組。

緩衝區寫入

使用重載五個版本的put()方法將數據寫入緩衝區。

  • put(int index,byte b)將指定的b數據寫入指定的索引。調用此方法不會更改緩衝區的當前位置。

  • put(byte b)將指定的字節寫入緩衝區的當前位置,並將位置遞增1

  • put(byte [] source,int offset,int length)將起始於偏移量的源數組的字節長度寫入從當前位置開始的緩衝區。 如果緩衝區中沒有足夠的空間來寫入所有字節,它會拋出BufferOverflowException。 緩衝區的位置按長度增加。put(byte [] source)與調用put(byte [] source,0,source.length)相同。

  • ByteBuffer put(ByteBuffer src)從指定的字節緩衝區src讀取剩餘的字節,並將它們寫入緩衝區。如果目標緩衝區中的剩餘空間小於源緩衝區中的剩餘字節,則拋出運行時BufferOverflowException

以下代碼顯示如何寫入緩衝區和從緩衝區讀取。

import java.nio.ByteBuffer;

public class Main {
  public static void main(String[] args) {
    ByteBuffer bb = ByteBuffer.allocate(8);
    printBufferInfo(bb);
    for (int i = 50; i < 58; i++) {
      bb.put((byte) i);
    }
    printBufferInfo(bb);
  }

  public static void printBufferInfo(ByteBuffer bb) {
    int limit = bb.limit();
    System.out.println("Position =  " + bb.position() + ", Limit   = " + limit);
    for (int i = 0; i < limit; i++) {
      System.out.print(bb.get(i) + "  ");
    }
    System.out.println();
  }
}

如果在緩衝區上使用get()put()方法來讀/寫至少一個元素,則緩衝區的hasRemaining()方法返回true

可以通過使用相對的get()put()方法,通過使用其remaining()方法來獲得可以讀/寫的最大數量的元素。

上面的代碼生成以下結果。

Position =  0, Limit   = 8
0  0  0  0  0  0  0  0  
Position =  8, Limit   = 8
50  51  52  53  54  55  56  57

示例

以下代碼顯示如何使用相對讀取和寫入緩衝區的flip()hasRemaining()方法。

import java.nio.ByteBuffer;

public class Main {
  public static void main(String[] args) {
    ByteBuffer bb = ByteBuffer.allocate(8);
    printBufferInfo(bb);

    // Use flip() to reset the position to zero because
    // the printBufferInfo() method uses relative get() method
    bb.flip();

    int i = 50;
    while (bb.hasRemaining()) {
      bb.put((byte) i++);
    }

    // Call flip() again to reset the position to zero,
    // because the above put() call incremented the position
    bb.flip();
    printBufferInfo(bb);
  }

  public static void printBufferInfo(ByteBuffer bb) {
    int limit = bb.limit();
    System.out.println("Position =  " + bb.position() + ", Limit   = " + limit);
    while (bb.hasRemaining()) {
      System.out.print(bb.get() + "  ");
    }
    System.out.println();
  }
}

上面的代碼生成以下結果。

Position =  0, Limit   = 8
0  0  0  0  0  0  0  0  
Position =  0, Limit   = 8
50  51  52  53  54  55  56  57

只讀緩衝區

緩衝區可以是隻讀的或讀寫的。只能讀取只讀緩衝區的內容。可以通過調用特定緩衝區類的asReadOnlyBuffer()方法來獲得只讀緩衝區。

// Create a  buffer that is read-write by  default
ByteBuffer bb  = ByteBuffer.allocate(1024);
boolean readOnly   = bb.isReadOnly(); // false

要檢查緩衝區是否爲只讀,請按如下所示調用isReadOnly()方法:

ByteBuffer bbReadOnly = bb.asReadOnlyBuffer();
boolean readOnly = bbReadOnly.isReadOnly();

asReadOnlyBuffer()方法返回的只讀緩衝區是同一個緩衝區的不同視圖。對原始緩衝區的內容的任何修改都反映在只讀緩衝區中。

緩衝區視圖

可以獲得緩衝區的不同視圖。緩衝區的視圖與原始緩衝區共享數據,並保持其自身的位置,標記和限制。
也可以複製一個緩衝區,在這種情況下,它們共享內容,但獨立地保持標記,位置和限制。 使用緩衝區的duplicate()方法獲取緩衝區的副本如下:

// Create a  buffer
ByteBuffer bb  = ByteBuffer.allocate(1024);

// Create a  duplicate view  of  the   buffer
ByteBuffer bbDuplicate = bb.duplicate();

還可以通過使用緩衝區的slice()方法創建其切片視圖,從而創建緩衝區的切片視圖,如下所示:

// Create a  buffer
ByteBuffer bb  = ByteBuffer.allocate(8);
bb.position(3);
bb.limit(6);
// bbSlice will have  position set to 0  and  its  limit set to 3. 
ByteBuffer bbSlice  = bb.slice();

還可以獲得用於不同原始數據類型的字節緩衝區的視圖。
例如,可以獲得字節緩衝區的字符視圖,浮點視圖等。 ByteBuffer類包含諸如asCharBuffer()asLongBuffer()asFloatBuffer()等方法來獲得原始數據類型的視圖。

// Create a  byte   buffer
ByteBuffer bb  = ByteBuffer.allocate(8);

// Create a  char   view  of  the   byte   buffer
CharBuffer cb  = bb.asCharBuffer();

// Create a  float view  of  the   byte   buffer
FloatBuffer fb  = bb.asFloatBuffer();