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

Java?NIO?Channel?使用詳情

 更新時間:2022年04月07日 11:09:57   作者:SH的全棧筆記  
這篇文章主要介紹了Java?NIO?Channel?使用詳情,文章圍繞主題展開詳細內(nèi)容需要的小伙伴可以參考一下,希望對你的學習有所幫助

Java NIO 中的 Channel 分類:

  • FileChannel
  • SocketChannel
  • ServerSocketChannel
  • DatagramChannel

Java NIO Channel 使用_FileChannel

FileChannel: 主要用于文件的讀寫,可以從磁盤上讀取文件,也可以向磁盤上寫入文件。

SocketChannel:用于 Socket 的 TCP 連接的數(shù)據(jù)讀寫,既可以從 Channel 讀數(shù)據(jù),也可以向 Channle 中寫入數(shù)據(jù)

ServerSocketChannel:通過 ServerSocketChannel 可以監(jiān)聽 TCP 連接,服務端監(jiān)聽到連接之后,會為每個請求創(chuàng)建一個 SocketChannel

DatagramChannel:用于 UDP 協(xié)議的數(shù)據(jù)讀寫

接下來就分別介紹一下。

FileChannel

主要用于操作文件,廢話不多說,直接看例子。

準備文件 test-file.txt ,內(nèi)容 shDEQuanZhanBiJi

Java NIO Channel 使用_SocketChannel_02

輸入 FileInputStream

用于從 FileChannel 中讀取數(shù)據(jù),例如將指定文件輸入到 FileChannel 中,我們就能獲取到文件的內(nèi)容,接下來編寫 FileChannel 的 輸入流 核心代碼:

public static void main(String[] args) throws IOException {
  // 創(chuàng)建一個輸入流
  FileInputStream fileInputStream = new FileInputStream("test-file.txt");
  // 通過輸入流獲取到 channel
  FileChannel fileChannel = fileInputStream.getChannel();

  // 準備好 ByteBuffer
  ByteBuffer buffer = ByteBuffer.allocate(16);
  // 將 輸入流 的 channel 的數(shù)據(jù)讀入 buffer 中
  fileChannel.read(buffer);

  // 簡單打印 buffer 的內(nèi)容
  printBuffer(buffer); // shDEQuanZhanBiJi
}

這里面的 ByteBuffer 是 channel 進行讀、寫數(shù)據(jù)的中間媒介。要從 channel 中讀取數(shù)據(jù)(也就是上面這個例子),需要先將數(shù)據(jù)讀到 ByteBuffer 中;同理,要想向 channel 中寫入數(shù)據(jù),也需要先將數(shù)據(jù)寫入 ByteBuffer(下面講輸出流的時候會講)。

對 ByteBuffer 不熟悉的可以先看看我之前寫的 《玩轉(zhuǎn) ByteBuffer》,printBuffer 的代碼里面也有

輸出 FileOutputStream

顧名思義,是 FileChannel 要向外輸出數(shù)據(jù),例如將數(shù)據(jù)寫入到磁盤文件上,接下來通過例子看看效果:

public static void main(String[] args) throws IOException {
  // 指定需要生成的文件名稱
  String generateFileName = "generate-file.txt";
  // 創(chuàng)建一個輸出流
  FileOutputStream fileOutputStream = new FileOutputStream(generateFileName);
  // 通過輸出流獲取到 channel
  FileChannel fileChannel = fileOutputStream.getChannel();

  // 準備好 ByteBuffer, 并向里面寫入數(shù)據(jù)
  ByteBuffer buffer = ByteBuffer.allocate(16);
  buffer.put("shDEQuanZhanBiJi".getBytes(StandardCharsets.UTF_8));

  // 將 輸入流 的 channel 的數(shù)據(jù)讀入 buffer 中
  fileChannel.write(buffer);
  fileChannel.close();
}

相應的注釋都已經(jīng)貼在對應的代碼上了,細節(jié)在此不再贅述。唯一需要關(guān)注的是,調(diào)用 write 寫文件到磁盤上時,也是先傳入的 ByteBuffer。

好了,當你運行完代碼你會發(fā)現(xiàn),雖然文件是生成的了,但是里面卻是空白的…這其實就涉及到對 ByteBuffer 的熟悉程度了,算是埋的一個坑。

如果不知道為啥文件是空的,可以去看看上面講 ByteBuffer 的文章,接下來是解答。

這是因為我們創(chuàng)建一個 ByteBuffer 的時候默認是處于寫模式的,此時如果去通過 position 和 limit 去讀取數(shù)據(jù)是讀不到的。所以在調(diào)用 write 之前,我們需要先將 ByteBuffer 切換到讀模式,

完整代碼如下:

public static void main(String[] args) throws IOException {
  // 指定需要生成的文件名稱
  String generateFileName = "generate-file.txt";
  // 創(chuàng)建一個輸出流
  FileOutputStream fileOutputStream = new FileOutputStream(generateFileName);
  // 通過輸出流獲取到 channel
  FileChannel fileChannel = fileOutputStream.getChannel();

  // 準備好 ByteBuffer, 并向里面寫入數(shù)據(jù)
  ByteBuffer buffer = ByteBuffer.allocate(16);
  buffer.put("shDEQuanZhanBiJi".getBytes(StandardCharsets.UTF_8));

  // 將 ByteBuffer 切換到讀模式
  buffer.flip();
  // 將 輸入流 的 channel 的數(shù)據(jù)讀入 buffer 中
  fileChannel.write(buffer);
  
  fileChannel.close();
}

可以看到,文件生成了,內(nèi)容也有了:

Java NIO Channel 使用_ServerSocketChannel_04

但是呢,上面將的兩種要么只能寫,要么只能讀。例如 FileInputStream 如果你硬要往 channel 里懟數(shù)據(jù),程序最后會拋出 NonWritableChannelException 異常,告訴你這玩意兒寫不了。

那有沒有一個既能寫,又能讀還能唱跳的實現(xiàn)呢?當然有,那就是 RandomAccessFile。

這里提一嘴,調(diào)用完 write 并不是立即就寫入磁盤,也可以在操作系統(tǒng)的緩存里。如果需要立即刷盤,則調(diào)用 channel.force(true); 即可。

RandomAccessFile

怎么用的呢?其實跟之前兩個差不多:

public static void main(String[] args) throws IOException {
  // 指定需要生成的文件名稱
  String targetFileName = "target-file.txt";
  // 創(chuàng)建 RandomAccessFile, 賦予可讀(r)、可寫(w)的權(quán)限
  RandomAccessFile accessFile = new RandomAccessFile(targetFileName, "rw");
  FileChannel fileChannel = accessFile.getChannel();

  // 創(chuàng)建 ByteBuffer 并寫入數(shù)據(jù)
  ByteBuffer buffer = ByteBuffer.allocate(16);
  buffer.put("shDEQuanZhanBiJi".getBytes(StandardCharsets.UTF_8));
  // 切換到 buffer 的讀模式
  buffer.flip();
  // 調(diào)用 write 將 buffer 的數(shù)據(jù)寫入到 channel, channel 再寫數(shù)據(jù)到磁盤文件
  fileChannel.write(buffer);

  // 相當于清空 buffer
  buffer.clear();
  // 將之前寫入到 channel 的數(shù)據(jù)再讀入到 buffer
  fileChannel.read(buffer);

  // 打印 buffer 中的內(nèi)容
  printBuffer(buffer);

  fileChannel.close();
}

運行之后的效果就是,會生成一個名為 target-file.txt 的文件,內(nèi)容就是 shDEQuanZhanBiJi。并且控制臺會將之前寫入 channel 的 shDEQuanZhanBiJi 打印出來。

老規(guī)矩,細節(jié)都在注釋中。值得注意的是 new RandomAccessFile(targetFileName, "rw"); 里的 rw 。注釋里也寫了,代表賦予可讀、可寫的權(quán)限。

再值得注意的是,你不能說把 rw 改成 w

不能這么玩,因為它就是一個單純的字符串匹配,可供選擇的就這么些:

可以看到,r 必不可少…:

  • r 只能讀
  • rw 既能,也能
  • rws 和 rwd 功能和 rw 大致是相同的,可讀、可寫。唯一區(qū)別是他們會將每次改動強制刷到磁盤,并且 rws 會將操作系統(tǒng)對該文件的元數(shù)據(jù)也一起刷盤,體現(xiàn)就是文件的更新時間會更新,而 rwd 不會將文件的元數(shù)據(jù)刷盤

兩個 SocketChannel

由于這倆一個負責連接傳輸,另一個負責連接的監(jiān)聽,所以就放在一起來講了。這一小節(jié)我們大概要做這件事:

Java NIO Channel 使用_FileChannel_08

但是為了能讓大家直接運行起來,客戶端這側(cè)就不從磁盤文件讀取了,直接用 ByteBuffer。大家可以運行起來之后,自己嘗試從磁盤上去加載。還是先看代碼,首先是服務器的:

ServerSocketChannel

public static void main(String[] args) throws IOException {
  // 打開一個 ServerSocketChannel
  ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
  // 綁定 8080 端口
  serverSocketChannel.bind(new InetSocketAddress(8080));

  // 開始接受客戶端連接
  SocketChannel socketChannel = serverSocketChannel.accept();
  // 獲取連接成功
  System.out.printf("socketChannel %s connected\n", socketChannel);
  // 準備 ByteBuffer 以從 socketChannel 中讀取數(shù)據(jù)
  ByteBuffer buffer = ByteBuffer.allocate(16);

  // 開始讀取數(shù)據(jù)
  System.out.println("before read");
  int read = socketChannel.read(buffer);
  System.out.printf("read complete, read bytes length: %s \n", read);

  printBuffer(buffer);
}

這里我們使用的是 Java NIO 中默認的阻塞模式,僅僅作為一個掩飾,如果想要 ServerSocketChannel 進入非阻塞模式,可在 open 之后,調(diào)用:

serverSocketChannel.configureBlocking(false);

由于我們這里是阻塞模式,所以在代碼運行到 serverSocketChannel.accept(); 時,會陷入阻塞狀態(tài),直到有客戶端過來建立連接。同理,read 方法也是阻塞的,如果客戶端一直沒有寫入數(shù)據(jù),那么服務器就會一直阻塞在 read 。

SocketChannel

直接先給代碼:

public static void main(String[] args) throws IOException {
  // 打開一個 SocketChannel
  SocketChannel socketChannel = SocketChannel.open();
  // 連接到 localhost 的 8080 端口
  socketChannel.connect(new InetSocketAddress("localhost", 8080));

  // 準備 ByteBuffer
  ByteBuffer buffer = ByteBuffer.allocate(16);
  buffer.put(Charset.defaultCharset().encode("test"));

  // 將 buffer 切換成讀模式 & 向 channel 中寫入數(shù)據(jù)
  buffer.flip();
  socketChannel.write(buffer);
}

先啟動服務器,再啟動客戶端??梢钥吹椒掌鱾?cè)的控制臺有如下的輸出:

socketChannel java.nio.channels.SocketChannel[connected local=/127.0.0.1:8080 remote=/127.0.0.1:64373] connected
before read
read complete, read bytes length: 4 
BUFFER VALUE: test

Datagram

這個就比較簡單,首先是客戶端的代碼:

public static void main(String[] args) throws IOException {
  DatagramChannel datagramChannel = DatagramChannel.open();

  // 構(gòu)建 buffer 數(shù)據(jù)
  ByteBuffer buffer = ByteBuffer.allocate(16);
  buffer.put(Charset.defaultCharset().encode("test"));

  // 切換到 buffer 的讀模式
  buffer.flip();
  datagramChannel.send(buffer, new InetSocketAddress("localhost", 8080));
}

然后是服務器:

public static void main(String[] args) throws IOException {
  DatagramChannel datagramChannel = DatagramChannel.open();
  datagramChannel.bind(new InetSocketAddress(8080));

  ByteBuffer buffer = ByteBuffer.allocate(16);
  datagramChannel.receive(buffer);

  printBuffer(buffer);
}

到此這篇關(guān)于Java NIO Channel 使用詳情的文章就介紹到這了,更多相關(guān)Java NIO Channel內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解java中List中set方法和add方法的區(qū)別

    詳解java中List中set方法和add方法的區(qū)別

    本文主要介紹了詳解java中List中set方法和add方法的區(qū)別,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • Java關(guān)鍵字之this用法詳解

    Java關(guān)鍵字之this用法詳解

    這篇文章將為大家詳細介紹一下Java關(guān)鍵字this的用法,文中有相關(guān)的代碼示例,希望對大家的學習或工作有一定的幫助,感興趣的同學可以參考下
    2023-05-05
  • Java8中新特性Optional、接口中默認方法和靜態(tài)方法詳解

    Java8中新特性Optional、接口中默認方法和靜態(tài)方法詳解

    Java 8 已經(jīng)發(fā)布很久了,很多報道表明Java 8 是一次重大的版本升級。下面這篇文章主要給大家介紹了關(guān)于Java8中新特性Optional、接口中默認方法和靜態(tài)方法的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下。
    2017-12-12
  • Spring session整合到Redis過程解析

    Spring session整合到Redis過程解析

    這篇文章主要介紹了Spring session整合到Redis過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-11-11
  • SpringBoot-RestTemplate實現(xiàn)調(diào)用第三方API的方式

    SpringBoot-RestTemplate實現(xiàn)調(diào)用第三方API的方式

    RestTemplate?是由?Spring?提供的一個?HTTP?請求工具,它提供了常見的REST請求方案的模版,例如?GET?請求、POST?請求、PUT?請求、DELETE?請求以及一些通用的請求執(zhí)行方法?exchange?以及?execute,下面看下SpringBoot?RestTemplate調(diào)用第三方API的方式
    2022-12-12
  • Java多線程處理List問題

    Java多線程處理List問題

    這篇文章主要介紹了Java多線程處理List問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • Java  匿名內(nèi)部類詳解及實例代碼

    Java 匿名內(nèi)部類詳解及實例代碼

    這篇文章主要介紹了Java 匿名內(nèi)部類詳解及實例代碼的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • mybatis修改int型數(shù)據(jù)無法修改成0的解決

    mybatis修改int型數(shù)據(jù)無法修改成0的解決

    這篇文章主要介紹了mybatis修改int型數(shù)據(jù)無法修改成0的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • 詳解Java如何通過Socket實現(xiàn)查詢IP

    詳解Java如何通過Socket實現(xiàn)查詢IP

    在本文中,我們來學習下如何找到連接到服務器的客戶端計算機的IP地址。我們將創(chuàng)建一個簡單的客戶端-服務器場景,讓我們探索用于TCP/IP通信的java.net?API,感興趣的可以了解一下
    2022-10-10
  • JavaWeb響應下載功能實例代碼(包含工具類)

    JavaWeb響應下載功能實例代碼(包含工具類)

    今天通過本文給大家分享的是關(guān)于javaweb的響應(response)下載功能,需要的朋友參考下吧
    2017-07-07

最新評論

南康市| 德州市| 保定市| 大英县| 玉溪市| 合水县| 桦南县| 天水市| 鹤峰县| 济阳县| 龙胜| 万山特区| 湾仔区| 吉木乃县| 自贡市| 涞源县| 敖汉旗| 西藏| 中牟县| 定南县| 即墨市| 山丹县| 古浪县| 桃园市| 巴林左旗| 神木县| 华坪县| 宾川县| 娄底市| 明光市| 梁平县| 屏山县| 莫力| 镇巴县| 华容县| 北安市| 和林格尔县| 开鲁县| 巴塘县| 临夏县| 台中市|