Java I/O緩沖區(qū)

2018-02-05 18:03 更新

Java IO教程 - Java I/O緩沖區(qū)

什么是NIO?

在NIO中,我們處理I/O操作的通道和緩沖區(qū)。

像流一樣的通道表示數(shù)據(jù)源/接收器和用于數(shù)據(jù)傳輸?shù)腏ava程序之間的連接。

通道提供雙向數(shù)據(jù)傳輸設(shè)施。我們可以使用通道來讀取數(shù)據(jù)以及寫入數(shù)據(jù)。根據(jù)我們的需要,我們可以獲得只讀通道,只寫通道或讀寫通道。

在基于流的I/O中,數(shù)據(jù)傳輸?shù)幕締挝皇且粋€字節(jié)。在基于通道的NIO中,數(shù)據(jù)傳輸?shù)幕締挝皇蔷彌_器。

緩沖區(qū)具有確定其可以包含的數(shù)據(jù)的上限的固定容量。

在基于通道的I/O中,我們將數(shù)據(jù)寫入緩沖區(qū),并將該緩沖區(qū)傳遞到寫入數(shù)據(jù)的通道。

為了從數(shù)據(jù)源讀取數(shù)據(jù),我們向一個通道傳遞一個緩沖區(qū)。通道將數(shù)據(jù)從數(shù)據(jù)源讀入緩沖區(qū)。


緩沖區(qū)

緩沖區(qū)是固定長度的數(shù)據(jù)容器。有一個單獨的緩沖區(qū)類型來保存每種類型的基本值的數(shù)據(jù),除了布爾類型值。

緩沖區(qū)是我們程序中的一個對象。我們有一個單獨的類來表示每種類型的緩沖區(qū)。

所有緩沖區(qū)類都繼承自一個抽象的Buffer類。包含原始值的緩沖區(qū)類如下:

  • ByteBuffer
  • ShortBuffer
  • CharBuffer
  • IntBuffer
  • LongBuffer
  • FloatBuffer
  • DoubleBuffer

不同的緩沖區(qū)保存不同數(shù)據(jù)類型的數(shù)據(jù)。例如,ByteBuffer保存字節(jié)值; ShortBuffer保存短值;一個CharBuffer保存字符,等等。


緩沖區(qū)屬性

以下是緩沖區(qū)的四個重要屬性。

  • Capacity
  • Position
  • Limit
  • Mark

緩沖區(qū)的容量是它可以容納的元素的最大數(shù)量。并且當(dāng)創(chuàng)建緩沖器時它是固定的。

我們可以通過調(diào)用hasArray()方法檢查緩沖區(qū)是否由數(shù)組支持,如果緩沖區(qū)由數(shù)組支持則返回true。

我們可以通過使用緩沖對象的array()方法來訪問支持數(shù)組。

一旦我們訪問了后臺數(shù)組,對該數(shù)組所做的任何更改都將反映在緩沖區(qū)中。

緩沖區(qū)具有返回其容量的capacity()方法。

緩沖區(qū)創(chuàng)建

我們可以使用特定緩沖區(qū)類的allocate()工廠方法創(chuàng)建一個緩沖區(qū),如下所示:

以下代碼創(chuàng)建一個容量為8的字節(jié)緩沖區(qū)

ByteBuffer bb  = ByteBuffer.allocate(8);

獲得容量

int capacity = bb.capacity();

以下代碼創(chuàng)建一個容量為1024的字符緩沖區(qū)

CharBuffer cb  = CharBuffer.allocate(1024);

字節(jié)緩沖區(qū)有一個名為allocateDirect()的方法,它創(chuàng)建一個字節(jié)緩沖區(qū),從操作系統(tǒng)內(nèi)存中分配內(nèi)存,而不是從JVM堆中分配內(nèi)存。

我們可以使用ByteBuffer類的isDirect()方法來檢查緩沖區(qū)是直接還是非直接。

// Create a  direct byte   buffer of  512  bytes capacity
ByteBuffer bbd = ByteBuffer.allocateDirect(512);

另一種創(chuàng)建緩沖區(qū)的方法是使用緩沖區(qū)的static wrap()方法包裝數(shù)組。

byte[]  byteArray = new byte[512];
ByteBuffer bb  = ByteBuffer.wrap(byteArray);

我們可以使用相同的技術(shù)來創(chuàng)建緩沖區(qū)來存儲其他原始值。

當(dāng)我們創(chuàng)建一個緩沖區(qū)時,緩沖區(qū)的所有元素都被初始化為零值。

緩沖區(qū)索引位置

緩沖區(qū)的每個元素都有一個索引。第一個元素的索引為0,最后一個元素的索引為capacity-1。

創(chuàng)建緩沖區(qū)時,其位置設(shè)置為0,其限制等于其容量。

我們可以使用它的重載position()方法獲取/設(shè)置緩沖區(qū)的位置。

position()方法返回緩沖區(qū)位置的當(dāng)前值。

position(int newPosition)方法將緩沖區(qū)的位置設(shè)置為指定的newPosition值,并返回緩沖區(qū)的引用。

我們可以使用它的重載limit()方法獲取/設(shè)置緩沖區(qū)的限制。

limit()方法返回緩沖區(qū)限制的當(dāng)前值。limit(int newLimit)方法將緩沖區(qū)的限制設(shè)置為指定的newLimit值,并返回緩沖區(qū)的引用。

我們可以使用mark()方法為緩沖區(qū)的位置添加書簽。當(dāng)我們調(diào)用mark()方法時,緩沖區(qū)將其位置的當(dāng)前值存儲為其標(biāo)記值。我們可以通過使用reset()方法將緩沖區(qū)的位置設(shè)置為之前加書簽的值。

緩沖區(qū)的標(biāo)記在創(chuàng)建時未定義。只有當(dāng)定義了它的標(biāo)記時,我們才必須在緩沖區(qū)上調(diào)用reset()方法。否則,reset()方法會拋出InvalidMarkException異常。

以下代碼創(chuàng)建一個新緩沖區(qū)并顯示其四個屬性。

import java.nio.ByteBuffer;
import java.nio.InvalidMarkException;

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

    System.out.println("Capacity: " + bb.capacity());
    System.out.println("Limit: " + bb.limit());
    System.out.println("Position: " + bb.position());

    // The mark is not set for a new buffer. Calling the
    // reset() method throws a runtime exception if the mark is not set.
    try {
      bb.reset();
      System.out.println("Mark: " + bb.position());
    } catch (InvalidMarkException e) {
      System.out.println("Mark is not  set");
    }
  }
}

上面的代碼生成以下結(jié)果。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號