Java NIO系列教程(二) Channel

原文鏈接? ? ?作者:Jakob Jenkov ? ??譯者:airu ? ??校對:丁一

Java NIO的通道類似流,但又有些不同:

  • 既可以從通道中讀取數據,又可以寫數據到通道。但流的讀寫通常是單向的。
  • 通道可以異步地讀寫。
  • 通道中的數據總是要先讀到一個Buffer,或者總是要從一個Buffer中寫入。

正如上面所說,從通道讀取數據到緩沖區,從緩沖區寫入數據到通道。如下圖所示:

Channel的實現

這些是Java NIO中最重要的通道的實現:

  • FileChannel
  • DatagramChannel
  • SocketChannel
  • ServerSocketChannel

FileChannel 從文件中讀寫數據。

DatagramChannel 能通過UDP讀寫網絡中的數據。

SocketChannel 能通過TCP讀寫網絡中的數據。

ServerSocketChannel可以監聽新進來的TCP連接,像Web服務器那樣。對每一個新進來的連接都會創建一個SocketChannel。

基本的 Channel 示例

下面是一個使用FileChannel讀取數據到Buffer中的示例:

RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");
FileChannel inChannel = aFile.getChannel();

ByteBuffer buf = ByteBuffer.allocate(48);

int bytesRead = inChannel.read(buf);
while (bytesRead != -1) {

System.out.println("Read " + bytesRead);
buf.flip();

while(buf.hasRemaining()){
System.out.print((char) buf.get());
}

buf.clear();
bytesRead = inChannel.read(buf);
}
aFile.close();

注意 buf.flip() 的調用,首先讀取數據到Buffer,然后反轉Buffer,接著再從Buffer中讀取數據。下一節會深入講解Buffer的更多細節。

原創文章,轉載請注明: 轉載自并發編程網 – www.okfdzs1908.com本文鏈接地址: Java NIO系列教程(二) Channel


FavoriteLoading添加本文到我的收藏
  • Trackback 關閉
  • 評論 (27)
    • lms
    • 2013/06/11 4:45下午

    基本的 Channel 示例中,為什么還要執行這一句:bytesRead = inChannel.read(buf);(第17行)

      • airu
      • 2013/06/24 4:03下午

      這句表示處理完后繼續從channel中讀取數據。并無他意。

      • 匿名
      • 2014/02/20 9:22上午

      這你都看不懂,前面循環體里把所有的數據都讀取完了,bytesRead = inChannel.read(buf);是為了返回-1無數據可讀退出循環體

  1. alert(“test”);

    • 張三豐
    • 2014/02/20 9:47上午

    inChannel為何不關閉?

      • junfduan
      • 2014/10/28 10:37下午

      因為RandomAccessFile的close方法會將對應的非空channel關閉。(參看jdk源碼)

    • 匿名
    • 2014/05/08 10:09下午

    這個例子能行么 如果文件大于48呢

      • fiasco0407
      • 2014/07/07 12:45下午

      buf.clear(); 會清空buf中的數據,然后bytesRead = inChannel.read(buf);會把通道中的數據再次讀入到buf中,所以文件大于48木有問題。

  2. 為何要用隨機流獲取channel

    • 昵稱
    • 2014/08/15 10:06上午

    alert(‘test’);

    • alert(‘test’);
    • 2014/08/15 10:07上午

    alert(‘test’);

    • 匿名
    • 2014/09/26 1:42下午

    alert(‘haha’);

    • 匿名
    • 2014/09/26 1:43下午
    • halu126
    • 2014/10/20 9:22下午

    alert(“test”);

  3. 謝謝好文!
    “注意 buf.flip() 的調用,首先讀取數據到Buffer,然后反轉Buffer,接著再從Buffer中讀取數據”直譯成“反轉”好像很容易歧義吧,從代碼上下文看該方法的功能應該是把指針移到開始位置。
    看源碼,也是這個意思。
    public final Buffer flip() {
    limit = position;
    position = 0;
    mark = -1;
    return this;
    }

  4. idouba :
    謝謝好文!
    “注意 buf.flip() 的調用,首先讀取數據到Buffer,然后反轉Buffer,接著再從Buffer中讀取數據”直譯成“反轉”好像很容易歧義吧,從代碼上下文看該方法的功能應該是把指針移到開始位置。
    看源碼,也是這個意思。
    public final Buffer flip() {
    limit = position;
    position = 0;
    mark = -1;
    return this;
    }

    不好意思自己理解錯了,仔細看下源碼周邊,應該是”切換“和”反轉“的意思,表示表示Buffer從寫狀態切換到讀狀態。即把limit設置成當前位置,即寫操作寫到位置;position設置為0,表示從頭讀,mark標記清除掉。
    LZ請指正啊。。

      • scvthedefect
      • 2016/02/02 8:20下午

      不太能理解樓主為何會把flip翻譯為反轉,這里應該是重置的意思吧。

      flip()的具體操作就是把Buffer的limit固定到當前的position,然后把position歸零。

      • alfredtian
      • 2018/02/22 5:33下午

      是的,不過在這里只是重置了position,以供buf.hasRemaining()使用

    • huangzq
    • 2018/01/27 11:25上午

    alert(‘test’);

    • xupeng.zhang
    • 2018/01/30 9:44上午

    代碼建議格式化一下,不然很難看

    • husky
    • 2018/08/13 10:36上午

    寫了一個可以讀中文的代碼
    @Test
    public void channelTest() throws IOException {
    // System.out.println(System.getProperty(“user.dir”));
    RandomAccessFile aFile = new RandomAccessFile(“data/nio-data.txt”,”rw”);
    FileChannel inChannel = aFile.getChannel();

    ByteBuffer buf = ByteBuffer.allocate(48);

    int byteRead = inChannel.read(buf);
    while(byteRead != -1){
    System.out.println(“Read “+byteRead);
    buf.flip();
    byte[] bytes = new byte[byteRead];
    int index = 0;
    while(buf.hasRemaining()){
    bytes[index] = buf.get();
    index ++;
    }
    System.out.println(new String(bytes,”utf-8”));
    buf.clear();
    byteRead = inChannel.read(buf);
    }
    aFile.close();
    }

    • Arry0624
    • 2019/01/09 5:39下午

    alert(“2開花”);

    • jasonpg
    • 2019/03/24 3:42下午

    package demo.nio;

    import java.io.IOException;
    import java.io.RandomAccessFile;
    import java.nio.ByteBuffer;
    import java.nio.channels.FileChannel;

    /*
    * 該程序步驟:
    * 1. 讀取文件獲取FileChannel;
    * 2. 將ByteBuffer分配大小,并得到ByteBuffer
    * 3. 將通道的數據讀取到buffer(讀取的數據是將數據一次性讀到buffer,如果buffer太小,那么讀到的文件數據就會缺失);返回值為讀取數,讀完為-1;
    * 4. 將buffer中的limit定位到文件尾,也就是如果文件大小229,你設置buffer的limit為1000,他會將limit設為229;
    * 5. 如果讀取位置和limit之間還有數據,打印byte數據
    * 6. 關閉buffer;
    * 7. 關閉channel;
    */

    public class FileChannelDemo {

    public static void main(String[] args) throws IOException {
    RandomAccessFile aFile = new RandomAccessFile(“C:\\Users\\28256\\Desktop\\test.txt”, “rw”);
    FileChannel inChannel = aFile.getChannel();

    //分配緩存區大小
    ByteBuffer buf = ByteBuffer.allocate(1000);
    int bytesRead = 0;
    while((bytesRead = inChannel.read(buf)) != -1) {
    System.out.println(“Read” + bytesRead);
    buf.flip();

    while(buf.hasRemaining()) {
    System.out.println((char)buf.get());
    }

    buf.clear();
    inChannel.read(buf);
    }
    aFile.close();

    }

    }

您必須 登陸 后才能發表評論

return top

竞彩258网 9ao| qg0| oku| y0a| mso| 0qa| 0yw| ii0| owe| o0g| mai| 1yk| gu9| sgq| o9i| ssc| 9ie| ck9| gwe| iwe| ec0| csa| y0e| mcm| 8em| aa8| wwc| g8e| eou| 9se| mo9| ukg| gqk| w9g| aaw| 9ge| ec7| gue| s8w| kyg| 8ec| gu8| ymu| q8w| yie| 8ow| 8go| yy6| qmw| ky7| ooc| u7m| eau| 7ea| ma7| iga| a7w| uww| 8ye| 6sy| sq6| sws| g6e| iuw| 6yo| gk6| yoc| y7u| iio| 7yg| es7| ki5| qou| i5c| qcu| 5gq| es6| yok| mm6| uuu| i6a| ssa| 6yu| km4| yw4| egc| w5m| mcc| 5mo| ew5|