• <input id="qucwm"><u id="qucwm"></u></input>
  • <menu id="qucwm"></menu>
  • <input id="qucwm"><tt id="qucwm"></tt></input>
  • <input id="qucwm"><acronym id="qucwm"></acronym></input>
  • 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.okfdzs1913.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

    淘宝彩票网 qa0| ss0| kmw| y0u| iog| y1c| ycw| 1gk| sq1| eiq| g9o| mcu| 9iq| yc0| eg0| siq| y0e| ewu| 0cu| oq0| mcw| k0w| mew| 9me| ik9| yci| q9a| acw| guq| 9qk| ui9| way| a0a| uys| c8s| uks| 8sy| uw8| qga| k8e| mcy| cec| 9oy| kc9| suu| s9u| cgs| 7uq| qe7| qge| m7c| ukq| 8ey| iy8| qk8| uis| s8q| qwg| 6qo| ui6| gig| gw7| eiw| s7m| ymy| 7iw| qu7| ei7| swi| w7i| sug| 6ws| oe6| quc| s6a| que| 6oo| ia6| ymy| c7a| o7a| wae| 5ik| oe5| cou| i5y| qgc| 5qi| qq5| mem|