JAVA-1NIO之Buffer

来源:http://www.cnblogs.com/zhangxinly/archive/2017/06/08/6961260.html
-Advertisement-
Play Games

註意:轉載自併發編程網,java nio系列教程 Buffer Java NIO中的Buffer用於和NIO通道進行交互。如你所知,數據是從通道讀入緩衝區,從緩衝區寫入到通道中的。 緩衝區本質上是一塊可以寫入數據,然後可以從中讀取數據的記憶體。這塊記憶體被包裝成NIO Buffer對象,並提供了一組方法 ...


註意:轉載自併發編程網,java nio系列教程

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中寫數據

寫數據到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之間的元素)


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 題目:做一個商場收銀的小程式,可能會出現的情況包括:正常收費,九折優惠,七折優惠,滿300減50等各種不同隨時會變化的優惠活動。 界面如下: 分析: 首先我們對於收錢寫一個父類CashSuper。這個父類是用來包含其他的各種收費方式的:正常收費、七折優惠、八折優惠、九折優惠、滿300減50、滿400 ...
  • 先定義枚舉 上面這個方法根據傳入的枚舉值通過反射獲得display中name的值 ...
  • 廢話不說直接上代碼; using MongoDB.Bson.Serialization.Attributes; namespace XL.Core.MongoDB { public interface IEntity<TKey> { /// <summary> /// 主鍵 /// </summar ...
  • 照著 利用表達式樹構建委托改善反射性能 做了一點小更改正好適合自己用 測試: ...
  • using System;using System.Collections.Generic;using System.Text;using System.Collections;using System.Data.SqlClient;using System.Data;using System.Co ...
  • 1,創建winform窗體應用程式 2,在界面上拖入DataGridView控制項 3,添加相應的列如圖: 4,開始編寫後面的代碼: private DataTable CountryDt = new DataTable(); private DataTable CityDt = new DataTa ...
  • 今天偶然間遇到的問題,搞不清緣由!但還是想記錄下來,點滴的記錄才能更快更好地成長!問題:如圖 IIS伺服器上運行正常,本地IIS運行調試就出現此問題! 經過IIS Express調試一次之後,本地IIS調試又恢復了正常!始終沒整明白到底是啥問題,以前從來沒有遇到過類似的問題!本人系初學菜鳥,如有大神 ...
  • 方案一: 調用線程式控制制方法.啟動:Thread.Start();停止:Thread.Abort();暫停:Thread.Suspend();繼續:Thread.Resume(); 線程定義為: 值得註意的是: 通過 Thread.Abort() 停下來的線程(或自行運行結束的線程),都無法直接通過 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...