最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java?NIO下ByteBuffer的常用方法學習

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

前言

咱就說,基礎不牢地動山搖,以前欠下的債遲早都要補回來,開始安排 Netty, 從 NIO 開始學起, 學習嘛, 肯定是先從案例開始學起

今日任務:

初步學習 NIO 中的 ByteBuffer

文件讀取案例

一個小小的案例, 讀取 test.txt 文件的內容, 四步走:

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

代碼展示

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

打印結果

test.txt文件內容如下所示

接下來執(zhí)行上述代碼, 結果如下

可以看到打印出來的結果是 ASCII 編碼表的值,所以我們把輸出轉為 char 類型, 結果如下

Buffer

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

今天開始學習 Netty ,那就繞不過 NIO, 在 NIO 包下的 Buffer 有以下七種實現(xiàn):

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

實際上就是八種數(shù)據(jù)類型的相關 Buffer, 但是我只聽說過 ByteBuffer, 也是使用最廣泛的, 至于為什么我也不知道, 希望以后有機會能過來填坑, 有大佬知道的話也可以評論區(qū)說一下

ByteBuffer常用方法

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

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

工具方法 selectAll()

為了方便觀察當前 ByteBuffer 所處的位置, 容量等信息, 寫了下面這個方法

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

打印結果如下:

根據(jù)打印結果我們可以很直觀的看到當前 ByteBuffer 每個下標上的元素是什么, 同時也能看到當前指針所處的位置(Position)

初始化

以下測試用例的 ByteBuffer 采用同一個 ByteBuffer

ByteBuffer buffer = ByteBuffer.allocate(16);

buffer.put()

put 方法就是往 ByteBuffer 中寫入數(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í)行結果如下:

圖中和代碼一樣, 是分兩次打印當前 ByteBuffer 的內容, pos 就是下一次寫入的下標

buffer.get()

get 方法是獲取元素的, 但是我們如果在剛寫入之后就去讀取的話, 是什么都讀取不到的, 具體如下所示

可以看到, 我們讀取出來當前的元素為 0, 我們進入源碼看一下 get 方法

如圖所示, 我們通過 get 方法獲取到的元素都是當前 pos 的下一個坐標元素, 在之前的 put 方法中, 我們看到最后 pos 是指向了 5 是下一個 寫入下標

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

  • 通過下標獲取
  • 將寫入模式更改為讀模式

通過下標獲取: 直接輸入下標就可以獲取到了

buffer.flip()

flip 方法: 將讀模式轉換為寫模式

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

這里 pos 代表的是下一個 get 的下標, lim 代表的是當前的長度

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

buffer.rewind()

rewind 方法可以理解為下標歸零, 也可以理解為重新開始, 重頭開始. 代碼展示如下所示

我們點進源代碼也可以看到, 它實際上就是將 pos 賦值了 0, 將 mark 賦值為 -1

buffer.mark() & buffer.reset()

這里將 mark 方法和 reset 方法一起講, 他倆是相輔相成的一個關系, 二者缺一不可
mark 方法標記當前下標, reset 回到 mark 標記的下標

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

buffer.clear() & buffer.compact()

clear 方法和 compact 方法都是對當前 ByteBuffer 寫入 , clear 方法是從頭開始寫入, compact 方法是將未讀內容移至頭部然后再寫入

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

可以看到, 在執(zhí)行完 compact 方法之后, 它先是將沒有讀取到的數(shù)據(jù)放置頭部, 在接下來 put 的時候對后面的內容進行了一個覆蓋

全部代碼

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);
        // 寫測試
        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()){
            // 準備緩沖區(qū)
            ByteBuffer buffer = ByteBuffer.allocate(10);
            // 循環(huán)遍歷
            while(true){
                // 從 channel 讀取數(shù)據(jù), 向 buffer 寫入
                int len = channel.read(buffer);
                if (len == -1){
                    System.out.println("沒有內容了");
                    break;
                }
                // 打印 buffer 內容
                // 切換至 讀模式
                buffer.flip();
                // 遍歷查看是否還有剩余未讀數(shù)據(jù)
                while(buffer.hasRemaining()){
                    byte b = buffer.get();
                    System.out.println((char) b);
                }
                // 切換為寫模式
                buffer.clear();
            }
        }catch (Exception e){
            System.out.println("文件未找到");
        }
    }
}

以上就是Java NIO下ByteBuffer的常用方法學習的詳細內容,更多關于Java ByteBuffer的資料請關注腳本之家其它相關文章!

相關文章

  • Java二維數(shù)組實戰(zhàn)案例

    Java二維數(shù)組實戰(zhàn)案例

    這篇文章主要介紹了Java二維數(shù)組,結合具體案例形式分析了java二維數(shù)組定義、遍歷、計算等相關操作技巧,需要的朋友可以參考下
    2019-08-08
  • JAVA 繼承基本類、抽象類、接口介紹

    JAVA 繼承基本類、抽象類、接口介紹

    Java是一個面向對象的語言,java面向對象一般有三大特征:封裝、繼承、多態(tài)
    2013-01-01
  • Java實戰(zhàn)練習之撲克牌魔術

    Java實戰(zhàn)練習之撲克牌魔術

    這篇文章主要介紹了Java實戰(zhàn)練習之撲克牌魔術,文中有非常詳細的代碼示例,對正在學習java的小伙伴們有很好地幫助,需要的朋友可以參考下
    2021-04-04
  • Java根據(jù)url生成圖片、截圖效果

    Java根據(jù)url生成圖片、截圖效果

    文章詳細介紹了如何使用Java和Node.js結合Puppeteer庫根據(jù)URL截圖,并將圖片轉換為標準輸出流返回給Java程序,本文通過實例代碼給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧
    2025-01-01
  • SpringBoot框架集成token實現(xiàn)登錄校驗功能

    SpringBoot框架集成token實現(xiàn)登錄校驗功能

    這篇文章主要為大家詳細介紹了SpringBoot框架集成token實現(xiàn)登錄校驗功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • Java性能調優(yōu)及排查方式

    Java性能調優(yōu)及排查方式

    這篇文章主要介紹了Java性能調優(yōu)及排查方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • maven依賴的配置和排除依賴過程

    maven依賴的配置和排除依賴過程

    這篇文章主要介紹了maven依賴的配置和排除依賴過程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • Java多線程實現(xiàn)阻塞隊列的示例代碼

    Java多線程實現(xiàn)阻塞隊列的示例代碼

    本文主要介紹了Java多線程實現(xiàn)阻塞隊列的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-12-12
  • 將Java的List結構通過GSON庫轉換為JSON的方法示例

    將Java的List結構通過GSON庫轉換為JSON的方法示例

    GONS是Google在GitHub上開源的Java類庫,提供各種Java對象和JSON格式對象之間的轉換功能,將Java的List結構通過GSON庫轉換為JSON的方法示例
    2016-06-06
  • 排序算法圖解之Java冒泡排序及優(yōu)化

    排序算法圖解之Java冒泡排序及優(yōu)化

    冒泡排序即通過對待排序的序列從前往后,依次比較相鄰元素的值,若發(fā)現(xiàn)逆序則交換位置,使較大的元素逐漸移動到后部。本文通過圖片和示例介紹了冒泡排序的實現(xiàn)及優(yōu)化,需要的可以參考一下
    2022-11-11

最新評論

曲沃县| 台山市| 景洪市| 石景山区| 东丰县| 库伦旗| 恩平市| 高碑店市| 全州县| 赤峰市| 卢氏县| 封丘县| 贵德县| 漳州市| 武清区| 黄浦区| 班戈县| 紫云| 兰西县| 佛冈县| 泾源县| 白山市| 大宁县| 湖州市| 荥阳市| 绿春县| 江陵县| 南华县| 青州市| 光山县| 沂南县| 吉首市| 香格里拉县| 恩平市| 通榆县| 文成县| 宁国市| 庆安县| 鲜城| 望江县| 合肥市|