欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java?NIO下ByteBuffer的常用方法學(xué)習(xí)

 更新時(shí)間:2023年05月16日 14:36:15   作者:寧軒  
這篇文章主要帶大家來(lái)初步學(xué)習(xí)一下NIO?中的?ByteBuffer的應(yīng)用與常用方法,文中的示例代碼講解詳細(xì),對(duì)我們深入學(xué)習(xí)Java有一定的幫助,感興趣的可以了解一下

前言

咱就說(shuō),基礎(chǔ)不牢地動(dòng)山搖,以前欠下的債遲早都要補(bǔ)回來(lái),開(kāi)始安排 Netty, 從 NIO 開(kāi)始學(xué)起, 學(xué)習(xí)嘛, 肯定是先從案例開(kāi)始學(xué)起

今日任務(wù):

初步學(xué)習(xí) NIO 中的 ByteBuffer

文件讀取案例

一個(gè)小小的案例, 讀取 test.txt 文件的內(nèi)容, 四步走:

  • 獲取文件流
  • 準(zhǔn)備緩沖區(qū)
  • 寫(xiě)入緩沖區(qū)
  • 遍歷讀取

代碼展示

private static void getFileContent(){
    // 輸入輸出流
    try(FileChannel channel = new FileInputStream("C:\Users\My\Desktop\learn\demo\demo\test.txt").getChannel()){
        // 準(zhǔn)備緩沖區(qū)
        ByteBuffer buffer = ByteBuffer.allocate(10);
        // 循環(huán)遍歷
        while(true){
            // 從 channel 讀取數(shù)據(jù), 向 buffer 寫(xiě)入
            int len = channel.read(buffer);
            if (len == -1){
                System.out.println("沒(méi)有內(nèi)容了");
                break;
            }
            // 打印 buffer 內(nèi)容
            // 切換至 讀模式
            buffer.flip();
            // 遍歷查看是否還有剩余未讀數(shù)據(jù)
            while(buffer.hasRemaining()){
                byte b = buffer.get();
                System.out.println(b);
            }
            // 切換為寫(xiě)模式
            buffer.clear();
        }
    }catch (Exception e){
        System.out.println("文件未找到");
    }
}

打印結(jié)果

test.txt文件內(nèi)容如下所示

接下來(lái)執(zhí)行上述代碼, 結(jié)果如下

可以看到打印出來(lái)的結(jié)果是 ASCII 編碼表的值,所以我們把輸出轉(zhuǎn)為 char 類(lèi)型, 結(jié)果如下

Buffer

Buffer繼承自O(shè)bject類(lèi),是基本類(lèi)型元素的線(xiàn)性有限序列(容器)。除內(nèi)容外,Buffer的基本屬性有:Limit—限制,Capacity—容量,Position—位置。對(duì)著三個(gè)變量操作,可以完成幾乎所有對(duì)Buffer的代碼操作。

今天開(kāi)始學(xué)習(xí) Netty ,那就繞不過(guò) NIO, 在 NIO 包下的 Buffer 有以下七種實(shí)現(xiàn):

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

實(shí)際上就是八種數(shù)據(jù)類(lèi)型的相關(guān) Buffer, 但是我只聽(tīng)說(shuō)過(guò) ByteBuffer, 也是使用最廣泛的, 至于為什么我也不知道, 希望以后有機(jī)會(huì)能過(guò)來(lái)填坑, 有大佬知道的話(huà)也可以評(píng)論區(qū)說(shuō)一下

ByteBuffer常用方法

在 java 中 ByteBuffer 的常用方法有以下七種:

  • put: 寫(xiě)入
  • get: 讀數(shù)據(jù)
  • flip: 切換讀模式
  • rewind: 重新重頭開(kāi)始讀
  • mark: 記錄當(dāng)前下標(biāo)
  • reset: 回到 mark 位置
  • clear: 切換寫(xiě)模式
  • compact: 切換寫(xiě)模式, 同時(shí)將未讀數(shù)據(jù)移動(dòng)到首部

工具方法 selectAll()

為了方便觀察當(dāng)前 ByteBuffer 所處的位置, 容量等信息, 寫(xiě)了下面這個(gè)方法

private static void selectAll(ByteBuffer buffer){
    System.out.println();
    int limit = buffer.limit();
    System.out.print("pos = " + buffer.position() + "     " + "lim = " + buffer.limit() + "     " + "cap = " + buffer.capacity());
    System.out.println();
    for (int i = 0; i < limit; i++) {
        if (i < 10){
            System.out.print(" |  ");
        }else{
            System.out.print(" | ");
        }
        System.out.print(i);
    }
    System.out.println();
    System.out.println("--------------------------------------------------------------------------");
    for (int i = 0; i < limit; i++) {
        byte b = buffer.get(i);
        System.out.print(" |  ");
        System.out.print((char) b);
        if (b == 0){
            System.out.print(0);
        }
    }
    System.out.println();
}

打印結(jié)果如下:

根據(jù)打印結(jié)果我們可以很直觀的看到當(dāng)前 ByteBuffer 每個(gè)下標(biāo)上的元素是什么, 同時(shí)也能看到當(dāng)前指針?biāo)幍奈恢?Position)

初始化

以下測(cè)試用例的 ByteBuffer 采用同一個(gè) ByteBuffer

ByteBuffer buffer = ByteBuffer.allocate(16);

buffer.put()

put 方法就是往 ByteBuffer 中寫(xiě)入數(shù)據(jù), 具體操作如下述代碼所示

private static void bufferPut(ByteBuffer buffer){
    buffer.put(new byte[]{'a', 'b', 'c', 'd'});
    selectAll(buffer);
    buffer.put(new byte[]{'1'});
    selectAll(buffer);
}

執(zhí)行結(jié)果如下:

圖中和代碼一樣, 是分兩次打印當(dāng)前 ByteBuffer 的內(nèi)容, pos 就是下一次寫(xiě)入的下標(biāo)

buffer.get()

get 方法是獲取元素的, 但是我們?nèi)绻趧倢?xiě)入之后就去讀取的話(huà), 是什么都讀取不到的, 具體如下所示

可以看到, 我們讀取出來(lái)當(dāng)前的元素為 0, 我們進(jìn)入源碼看一下 get 方法

如圖所示, 我們通過(guò) get 方法獲取到的元素都是當(dāng)前 pos 的下一個(gè)坐標(biāo)元素, 在之前的 put 方法中, 我們看到最后 pos 是指向了 5 是下一個(gè) 寫(xiě)入下標(biāo)

我們有兩種方法可以獲取到元素:

  • 通過(guò)下標(biāo)獲取
  • 將寫(xiě)入模式更改為讀模式

通過(guò)下標(biāo)獲取: 直接輸入下標(biāo)就可以獲取到了

buffer.flip()

flip 方法: 將讀模式轉(zhuǎn)換為寫(xiě)模式

還是剛才的例子, 使用方法 buffer.flip() 之后, 可以看到 pos 變成了 1, lim 變成了 5 , cap 不變

這里 pos 代表的是下一個(gè) get 的下標(biāo), lim 代表的是當(dāng)前的長(zhǎng)度

注意: 在調(diào)用 flip 進(jìn)入讀模式之后,后續(xù)如果調(diào)用 get() 導(dǎo)致 position 大于等于了 limit 的值,程序會(huì)拋出 BufferUnderflowException 異常。這點(diǎn)從之前 get 的源碼也可以看出來(lái)。

buffer.rewind()

rewind 方法可以理解為下標(biāo)歸零, 也可以理解為重新開(kāi)始, 重頭開(kāi)始. 代碼展示如下所示

我們點(diǎn)進(jìn)源代碼也可以看到, 它實(shí)際上就是將 pos 賦值了 0, 將 mark 賦值為 -1

buffer.mark() & buffer.reset()

這里將 mark 方法和 reset 方法一起講, 他倆是相輔相成的一個(gè)關(guān)系, 二者缺一不可
mark 方法標(biāo)記當(dāng)前下標(biāo), reset 回到 mark 標(biāo)記的下標(biāo)

可以看到, 當(dāng)我們執(zhí)行 mark 方法的時(shí)候記錄了當(dāng)前的下標(biāo), 執(zhí)行 reset 方法的時(shí)候 pos 又更改為了 1

buffer.clear() & buffer.compact()

clear 方法和 compact 方法都是對(duì)當(dāng)前 ByteBuffer 寫(xiě)入 , clear 方法是從頭開(kāi)始寫(xiě)入, compact 方法是將未讀內(nèi)容移至頭部然后再寫(xiě)入

可以看到, 在執(zhí)行完 clear 方法之后, 新增的元素是從下標(biāo) 0 開(kāi)始寫(xiě)入的

可以看到, 在執(zhí)行完 compact 方法之后, 它先是將沒(méi)有讀取到的數(shù)據(jù)放置頭部, 在接下來(lái) put 的時(shí)候?qū)竺娴膬?nèi)容進(jìn)行了一個(gè)覆蓋

全部代碼

import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/**
 * @Author ningxuan
 * @Date 2022/10/31 21:28
 */
public class ByteBufferTest {
    public static void main(String[] args) {
        // 讀文件案例
//        getFileContent();
        // 初始化 ByteBuffer
        ByteBuffer buffer = ByteBuffer.allocate(16);
        // 寫(xiě)測(cè)試
        bufferPut(buffer);  // a , b , c , d, 1
        bufferGet(buffer);
        buffer.flip();
//        System.out.println((char) buffer.get());    // a    pos == 0
//        System.out.println((char)buffer.get());     // b    pos == 1
//        buffer.rewind();
//        System.out.println((char)buffer.get());     // c    pos == 0
//        System.out.println((char)buffer.get());     // d    pos == 1
//        bufferMarkTest(buffer);
        bufferCompact(buffer);
    }
    private static void bufferCompact(ByteBuffer buffer){
        selectAll(buffer);
        buffer.get();
        buffer.get();
        selectAll(buffer);
        buffer.compact();
        selectAll(buffer);
        buffer.put(new byte[]{'e', 'h'});
        selectAll(buffer);
    }
    private static void bufferClear(ByteBuffer buffer){
        selectAll(buffer);
        System.out.println();
        buffer.clear();
        buffer.put(new byte[]{'e', 'h'});
        selectAll(buffer);
    }
    private static void bufferMarkTest(ByteBuffer buffer){
        byte b;
        b = buffer.get();   // a
        System.out.println((char) b);
        buffer.mark();
        System.out.println("position = " + buffer.position());
        b = buffer.get();   // b
        System.out.println((char) b);
        b = buffer.get();   // c
        System.out.println((char) b);
        buffer.reset();
        System.out.println("position = " + buffer.position());
        b = buffer.get();   // b
        System.out.println((char) b);
        b = buffer.get();   // c
        System.out.println((char) b);
    }
    private static void bufferGet(ByteBuffer buffer){
        byte b = buffer.get(0);
//        System.out.println((char)b);
        b = buffer.get(1);
//        System.out.println((char)b);
    }
    private static void bufferPut(ByteBuffer buffer){
        buffer.put(new byte[]{'a', 'b', 'c', 'd'});
//        selectAll(buffer);
        buffer.put(new byte[]{'1'});
//        selectAll(buffer);
    }
    private static void selectAll(ByteBuffer buffer){
        System.out.println();
        int limit = buffer.limit();
        System.out.print("pos = " + buffer.position() + "     " + "lim = " + buffer.limit() + "     " + "cap = " + buffer.capacity());
        System.out.println();
        for (int i = 0; i < limit; i++) {
            if (i < 10){
                System.out.print(" |  ");
            }else{
                System.out.print(" | ");
            }
            System.out.print(i);
        }
        System.out.println();
        System.out.println("--------------------------------------------------------------------------");
        for (int i = 0; i < limit; i++) {
            byte b = buffer.get(i);
            System.out.print(" |  ");
            System.out.print((char) b);
            if (b == 0){
                System.out.print(0);
            }
        }
        System.out.println();
    }
    private static void getFileContent(){
        // 輸入輸出流
        try(FileChannel channel = new FileInputStream("C:\Users\My\Desktop\learn\demo\demo\test.txt").getChannel()){
            // 準(zhǔn)備緩沖區(qū)
            ByteBuffer buffer = ByteBuffer.allocate(10);
            // 循環(huán)遍歷
            while(true){
                // 從 channel 讀取數(shù)據(jù), 向 buffer 寫(xiě)入
                int len = channel.read(buffer);
                if (len == -1){
                    System.out.println("沒(méi)有內(nèi)容了");
                    break;
                }
                // 打印 buffer 內(nèi)容
                // 切換至 讀模式
                buffer.flip();
                // 遍歷查看是否還有剩余未讀數(shù)據(jù)
                while(buffer.hasRemaining()){
                    byte b = buffer.get();
                    System.out.println((char) b);
                }
                // 切換為寫(xiě)模式
                buffer.clear();
            }
        }catch (Exception e){
            System.out.println("文件未找到");
        }
    }
}

以上就是Java NIO下ByteBuffer的常用方法學(xué)習(xí)的詳細(xì)內(nèi)容,更多關(guān)于Java ByteBuffer的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java使用fastjson對(duì)String、JSONObject、JSONArray相互轉(zhuǎn)換

    Java使用fastjson對(duì)String、JSONObject、JSONArray相互轉(zhuǎn)換

    這篇文章主要介紹了Java使用fastjson對(duì)String、JSONObject、JSONArray相互轉(zhuǎn)換,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • 詳解spring boot實(shí)現(xiàn)多數(shù)據(jù)源代碼實(shí)戰(zhàn)

    詳解spring boot實(shí)現(xiàn)多數(shù)據(jù)源代碼實(shí)戰(zhàn)

    本篇文章主要介紹了詳解spring boot實(shí)現(xiàn)多數(shù)據(jù)源代碼實(shí)戰(zhàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-07-07
  • IntelliJ IDEA中Scala、sbt、maven配置教程

    IntelliJ IDEA中Scala、sbt、maven配置教程

    這篇文章主要介紹了IntelliJ IDEA中Scala、sbt、maven配置教程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • 一文詳解java如何實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用

    一文詳解java如何實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用

    從?Java?8?開(kāi)始,便引入了一種稱(chēng)為“流式?API”的編程風(fēng)格,當(dāng)然也被稱(chēng)為“鏈?zhǔn)皆O(shè)置”或“鏈?zhǔn)秸{(diào)用”,本文主要來(lái)和大家討論一下如何實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用,感興趣的可以了解下
    2023-12-12
  • FreeMarker配置(Configuration)

    FreeMarker配置(Configuration)

    所有與該configuration 對(duì)象關(guān)聯(lián)的模版實(shí)例都就可以通過(guò)獲得to_upper 轉(zhuǎn)換器,company 來(lái)獲得字符串,因此你不需要再一次次的往root 中添加這些變量了。如果你往root 添加同名的變量,那么你新添加的變量將會(huì)覆蓋之前的共享變量。
    2016-04-04
  • Springboot使用@WebListener?作為web監(jiān)聽(tīng)器的過(guò)程解析

    Springboot使用@WebListener?作為web監(jiān)聽(tīng)器的過(guò)程解析

    這篇文章主要介紹了Springboot使用@WebListener作為web監(jiān)聽(tīng)器的過(guò)程,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-08-08
  • Java用list儲(chǔ)存,遍歷,查詢(xún)指定信息過(guò)程詳解

    Java用list儲(chǔ)存,遍歷,查詢(xún)指定信息過(guò)程詳解

    這篇文章主要介紹了Java用list儲(chǔ)存,遍歷,查詢(xún)指定信息過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • IDEA .iml文件及.idea文件夾超詳細(xì)講解

    IDEA .iml文件及.idea文件夾超詳細(xì)講解

    iml文件是IntelliJ IDEA自己創(chuàng)建的模塊文件,用于java應(yīng)用開(kāi)發(fā),存儲(chǔ)一些模塊相關(guān)的信息,比如一個(gè)Java組建,插件組建,Maven組建等,這篇文章主要介紹了IDEA .iml文件及.idea文件夾,需要的朋友可以參考下
    2023-09-09
  • 淺談JAVA 異常對(duì)于性能的影響

    淺談JAVA 異常對(duì)于性能的影響

    Java的異常處理為什么會(huì)影響性能?異常開(kāi)銷(xiāo)很大。那么,這是不是就意味著您不該使用異常?當(dāng)然不是。但是,何時(shí)應(yīng)該使用異常,何時(shí)又不應(yīng)該使用異常呢?不幸的是,答案不是一下子就說(shuō)得清楚的,我們來(lái)詳細(xì)探討下。
    2015-05-05
  • mybatis如何對(duì)大量數(shù)據(jù)的游標(biāo)查詢(xún)

    mybatis如何對(duì)大量數(shù)據(jù)的游標(biāo)查詢(xún)

    這篇文章主要介紹了mybatis如何對(duì)大量數(shù)據(jù)的游標(biāo)查詢(xún)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01

最新評(píng)論