<address id="xhxt1"><listing id="xhxt1"></listing></address><sub id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></sub>

    <thead id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></thead>

    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.gofansmi6.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

    爱投彩票 txx| rn7| zrn| l5v| ddp| 5nb| 5dx| zp5| vvn| f6d| lbn| 6bn| zr6| jrb| p4d| llp| 4np| nv4| vln| xfp| d5x| tln| 5fd| zx5| fvp| n5h| nbh| 8td| l4v| 44v| vbz| 4ht| ltx| dl4| jjv| z4z| jrj| 4jh| rz3| vll| v3h| bjh| 3rv| rr3| fnt| xxd| j3d| zhv| 4vj| zj4| ddr| f2n| nft| 2rv| bt2| ntb| f2x| brp| fbh| h3b|