搜尋
首頁Javajava教程JAVA之Buffer的用法

JAVA之Buffer的用法

Jun 25, 2017 am 10:14 AM
buffer

注意:轉載自並發程式設計網,java nio系列教學

1、Buffer

Java NIO中的Buffer用於和NIO通道進行互動。如你所知,資料是從通道讀入緩衝區,從緩衝區寫入到通道中的。

緩衝區本質上是一塊可以寫入數據,然後可以從中讀取資料的記憶體。這塊記憶體被包裝成NIO Buffer對象,並提供了一組方法,用來方便的存取該區塊記憶體。

一、Buffer的基本用法

使用Buffer讀寫資料一般會遵循以下四個步驟:

  1. 寫入資料到Buffer

  2. 呼叫flip()方法

  3. #從Buffer讀取資料:如直接讀取或讀取到Channel

  4. 呼叫clear()方法或compact()方法

當向buffer寫入數據時,buffer會記錄下寫了多少數據。一旦要讀取數據,需要透過flip()方法將Buffer從寫入模式切換到讀取模式。在讀取模式下,可以讀取之前寫入到buffer的所有資料。

一旦讀完了所有的數據,就需要清空緩衝區,讓它可以再次寫入。有兩種方式能清空緩衝區:呼叫clear()或compact()方法。 clear()方法會清空整個緩衝區。 compact()方法只會清除已經讀過的資料。任何未讀的資料都會移到緩衝區的起始處,新寫入的資料會放到緩衝區未讀資料的後面。

 

二、Buffer的capacity,position和limit

緩衝區本質上是一塊可以寫入數據,然後可以從中讀取資料的記憶體。這塊記憶體被包裝成NIO Buffer對象,並提供了一組方法,用來方便的存取該區塊記憶體。

為了理解Buffer的工作原理,需要熟悉它的三個屬性:

  • #capacity

  • position

  • limit

position和limit的意思取決於Buffer處在讀取模式還是寫入模式。不管Buffer處在什麼模式,capacity的意思總是一樣的。

這裡有一個關於capacity,position和limit在讀寫模式中的說明,詳細的解釋在插圖後面。

capacity:容量

作為記憶體區塊,Buffer有一個固定的大小值,也叫「capacity」.你只能往裡面寫capacity個byte、long,char等類型。一旦Buffer滿了,需要將其清空(透過讀取資料或清除資料)才能繼續寫入資料往裡面寫資料。

position:目前位置

當你寫資料到Buffer中時,position表示目前的位置。初始的position值為0.當一個byte、long等資料寫到Buffer後, position會向前移動到下一個可插入資料的Buffer單元。 position最大可為capacity – 1.

當讀取資料時,也是從某個特定位置讀取。當將Buffer從寫模式切換到讀取模式,position會被重置為0. 當從Buffer的position處讀取資料時,position向前移動到下一個可讀的位置。

limit:最大可寫/可讀位置

在寫入模式下,Buffer的limit表示你最多能往Buffer裡寫多少資料。 寫入模式下,limit等於Buffer的capacity。

當切換Buffer到讀取模式時, limit表示你最多能讀到多少資料。因此,當切換Buffer到讀取模式時,limit會被設定成寫模式下的position值。換句話說,你能讀到之前寫入的所有資料(limit被設定成已寫資料的數量,這個值在寫模式下就是position)

三、Buffer的型別

Java NIO 有以下Buffer類型

  • ByteBuffer

  • MappedByteBuffer

  • CharBuffer

  • #DoubleBuffer

  • FloatBuffer

  • #IntBuffer

  • LongBuffer

  • ShortBuffer

如你所見,這些Buffer類型代表了不同的資料型別。換句話說,就是可以透過char,short,int,long,float 或 double型別來操作緩衝區中的位元組。

MappedByteBuffer 有些特別,在涉及它的專門章節中再講。

四、Buffer的分配

要想取得一個Buffer物件首先要分配。 每一個Buffer類別都有一個allocate方法。下面是一個分配50位元組capacity的ByteBuffer的範例。

ByteBuffer buf = ByteBuffer.allocate(50);

 

 

#五、寫入資料

 
  • #寫資料到Buffer有兩種方式:
  • 從Channel寫到Buffer。

透過Buffer的put()方法寫到Buffer裡。

###初始化Buffer的時候放入byte數組寫入Buffer#############
public void test1() throws FileNotFoundException {//初始化容量ByteBuffer buf1 = ByteBuffer.allocate(48);//通过数组初始化,并将数组中的值放入缓冲区byte[] bytes = "123".getBytes();
        ByteBuffer buf2 = ByteBuffer.wrap(bytes);//将通道中的读到缓冲区int bytesRead = channel.read(bf);//通过put方法写入缓冲区,put有很多重载        buf1.put(bytes);
    }
###### ###### ## #

put方法有很多版本,允许你以不同的方式把数据写入到Buffer中。例如, 写到一个指定的位置,或者把一个字节数组写入到Buffer。 

flip()方法

flip方法将Buffer从写模式切换到读模式。调用flip()方法会将position设回0,并将limit设置成之前position的值。

换句话说,position现在用于标记读的位置,limit表示之前写进了多少个byte、char等 —— 现在能读取多少个byte、char等。

六、从Buffer中读取数据

从Buffer中读取数据有两种方式:

  1. 从Buffer读取数据到Channel。

  2. 使用get()方法从Buffer中读取数据。

        //将缓冲区的数据写入通道        channel.write(buf1);//通过get方法获取缓冲区中数据 get有很多重载buf1.get();

 

 

get方法有許多版本,讓你以不同的方式從Buffer中讀取資料。例如,從指定position讀取,或從Buffer中讀取資料到位元組數組。

七、rewind()方法:重設position

Buffer.rewind()將position設為0,所以你可以重讀Buffer中的所有資料。 limit保持不變,仍然表示能從Buffer中讀取多少個元素(byte、char等)。

八、clear()與compact()方法

一旦讀完Buffer中的數據,就需要讓Buffer準備好再寫入。可以透過clear()或compact()方法來完成。

如果呼叫的是clear()方法,position將被設回0,limit被設定為 capacity的值。換句話說,Buffer 被清空了。 Buffer中的資料並未清除,只是這些標記告訴我們可以從哪裡開始往Buffer裡寫資料。

如果Buffer中有一些未讀的數據,呼叫clear()方法,數據將“被遺忘”,意味著不再有任何標記會告訴你哪些數據被讀過,哪些還沒有。

如果Buffer中仍有未讀的數據,且後續還需要這些數據,但此時想要先寫些數據,那麼就使用compact()方法。

compact()方法將所有未讀的資料拷貝到Buffer起始處。然後將position設到最後一個未讀元素正後面。 limit屬性依然像clear()方法一樣,設定成capacity。現在Buffer準備好寫資料了,但是不會覆蓋未讀的資料。

九、mark()與reset()方法:標記位置和回傳位置

透過呼叫Buffer.mark()方法,可以標記Buffer中的一個特定position。之後可以透過呼叫Buffer.reset()方法恢復到這個position。例如:

十、equals()與compareTo()方法

可以使用equals()和compareTo()方法比較兩個Buffer。

equals()

當滿足下列條件時,表示兩個Buffer相等:

  1. 有相同的型別(byte、char、int等)。

  2. Buffer中剩餘的byte、char等的個數相等。

  3. Buffer中所有剩餘的byte、char等都相同。

如你所見,equals只是比較Buffer的一部分,不是每個在它裡面的元素都比較。實際上,它只比較Buffer中的剩餘元素。

compareTo()方法

compareTo()方法比較兩個Buffer的剩餘元素(byte、char等), 如果滿足下列條件,則認為一個Buffer「小於」另一個Buffer:

  1. 第一個不相等的元素小於另一個Buffer中對應的元素。

  2. 所有元素都相等,但第一個Buffer比另一個先耗盡(第一個Buffer的元素個數比另一個少)。

(譯:剩餘元素是從position到limit之間的元素)

2、Buffer之Scatter/Gather

  所謂的Scatter和Gather就是通道對應多個快取:將一個通道讀出到多個快取;將多個快取寫入到一個通道

  Java NIO開始支援scatter/gather,scatter/gather用於描述從Channel(譯者註:Channel在中文經常翻譯為通道)中讀取或寫入到Channel的操作。

  分散(scatter)從Channel中讀取是指在讀取操作時將讀取的資料寫入多個buffer。因此,Channel將從Channel中讀取的資料「分散(scatter)」到多個Buffer中

  聚集(gather)寫入Channel是指在寫入操作時將多個buffer的資料寫入同一個Channel,因此,Channel 將多個Buffer中的資料「聚集(gather)」後發送到Channel。

  scatter / gather經常用於需要將傳輸的資料分開處理的場合,例如傳輸一個由訊息頭和訊息體組成的訊息,你可能會將訊息體和訊息頭分散到不同的buffer中,這樣你可以方便的處理訊息頭和訊息體。

Scattering Reads
Scattering Reads是指資料從一個channel讀取到多個buffer中。如下圖說明:

Java NIO: Scattering Read

Java NIO: Scattering Read

#

注意buffer首先被插入到数组,然后再将数组作为channel.read() 的输入参数。read()方法按照buffer在数组中的顺序将从channel中读取的数据写入到buffer,当一个buffer被写满后,channel紧接着向另一个buffer中写。

Scattering Reads在移动下一个buffer前,必须填满当前的buffer,这也意味着它不适用于动态消息(译者注:消息大小不固定)。换句话说,如果存在消息头和消息体,消息头必须完成填充(例如 128byte),Scattering Reads才能正常工作。

Gathering Writes

Gathering Writes是指数据从多个buffer写入到同一个channel。如下图描述:

Java NIO: Gathering Write

Java NIO: Gathering Write

 

buffers数组是write()方法的入参,write()方法会按照buffer在数组中的顺序,将数据写入到channel,注意只有position和limit之间的数据才会被写入。因此,如果一个buffer的容量为128byte,但是仅仅包含58byte的数据,那么这58byte的数据将被写入到channel中。因此与Scattering Reads相反,Gathering Writes能较好的处理动态消息

    ByteBuffer header = ByteBuffer.allocate(128);
    ByteBuffer body   = ByteBuffer.allocate(1024);
    ByteBuffer[] bufferArray = { header, body };
    channel.read(bufferArray);  //传入Buffer数组即可//方便展示、直接写,写之前要反转bufferchannel.write(bufferArray);

 

以上是JAVA之Buffer的用法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前By尊渡假赌尊渡假赌尊渡假赌
威爾R.E.P.O.有交叉遊戲嗎?
1 個月前By尊渡假赌尊渡假赌尊渡假赌

熱工具

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。