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 are closed
  • Comments (21)
    • lms
    • 06/11. 2013 4:45pm

    基本的 Channel 示例中,为什么还要执行这一句:bytesRead = inChannel.read(buf);(第17行)

      • airu
      • 06/24. 2013 4:03pm

      这句表示处理完后继续从channel中读取数据。并无他意。

      • Anonymous
      • 02/20. 2014 9:22am

      这你都看不懂,前面循环体里把所有的数据都读取完了,bytesRead = inChannel.read(buf);是为了返回-1无数据可读退出循环体

  1. alert(“test”);

    • 张三丰
    • 02/20. 2014 9:47am

    inChannel为何不关闭?

      • junfduan
      • 10/28. 2014 10:37pm

      因为RandomAccessFile的close方法会将对应的非空channel关闭。(参看jdk源码)

    • Anonymous
    • 05/08. 2014 10:09pm

    这个例子能行么 如果文件大于48呢

      • fiasco0407
      • 07/07. 2014 12:45pm

      buf.clear(); 会清空buf中的数据,然后bytesRead = inChannel.read(buf);会把通道中的数据再次读入到buf中,所以文件大于48木有问题。

  2. 为何要用随机流获取channel

    • 昵称
    • 08/15. 2014 10:06am

    alert(‘test’);

    • alert(‘test’);
    • 08/15. 2014 10:07am

    alert(‘test’);

    • Anonymous
    • 09/26. 2014 1:42pm

    alert(‘haha’);

    • Anonymous
    • 09/26. 2014 1:43pm
    • halu126
    • 10/20. 2014 9:22pm

    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
      • 02/02. 2016 8:20pm

      不太能理解楼主为何会把flip翻译为反转,这里应该是重置的意思吧。

      flip()的具体操作就是把Buffer的limit固定到当前的position,然后把position归零。

You must be logged in to post a comment.

return top