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的更多细节。

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: Java NIO系列教程(二) Channel


airu

爱生活, 爱编码,更爱玩。
FavoriteLoading添加本文到我的收藏
  • Trackback 关闭
  • 评论 (21)
    • 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归零。

您必须 登陆 后才能发表评论

return top