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();