什么是通道Channel

这个说实话挺难定义的,有点抽象,不过我们可以根据它的用途来理解;

通道主要用于传输数据,从缓冲区的一侧传到另一侧的实体(如文件、套接字...),反之亦然;

通道是访问IO服务的导管,通过通道,我们可以以最小的开销来访问操作系统的I/O服务;

顺便说下,缓冲区是通道内部发送数据和接收数据的端点,如下图所示;

另外,关于通道Channel接口的定义,很简单,只有两个方法,判断通道是否打开和关闭通道;

public interface Channel extends Closeable {

    public boolean isOpen();

    public void close() throws IOException;

}

创建通道

通道主要分为两大类,文件(File)通道和套接字(socket)通道;

涉及的类有FileChannel类和三个socket通道类:SocketChannel、ServerSocketChannel和DatagramChannel;

下面分别看下这几个通道是如何创建的:

创建FileChannel通道

FileChannel通道只能通过在一个打开的RandomAccessFile、FileInputStream或FileOutputStream对象上调用getChannel( )方法来获取,如下所示:

        RandomAccessFile raf = new RandomAccessFile ("somefile", "r");
FileChannel fc = raf.getChannel( );

创建SocketChannel通道

        SocketChannel sc = SocketChannel.open( );
sc.connect (new InetSocketAddress ("somehost", someport));

创建ServerSocketChannel通道

        ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress(somelocalport));

创建DatagramChannel通道

        DatagramChannel dc = DatagramChannel.open( );

使用通道

在使用通道的时候,我们通常都将通道的数据取出存入ByteBuffer对象或者从ByteBuffer对象中获取数据放入通道进行传输;

在使用通道的过程中,我们要注意通道是单向通道还是双向通道,单向通道只能读或写,而双向通道是可读可写的;

如果一个Channel类实现了ReadableByteChannel接口,则表示其是可读的,可以调用read()方法读取;

如果一个Channel类实现了WritableByteChannel接口,则表示其是可写的,可以调用write()方法写入;

如果一个Channel类同时实现了ReadableByteChannel接口和WritableByteChannel接口则为双向通道,如果只实现其中一个,则为单向通道;

如ByteChannel就是一个双向通道,实际上ByteChannel接口本身并不定义新的API方法,它是一个聚集了所继承的多个接口,并重新命名的便捷接口;

如下是一个使用通道的例子,展示了两个通道之间拷贝数据的过程,已添加了完整的注释:

package nio;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel; public class Main
{ public static void main(String[] args) throws IOException
{
ReadableByteChannel source = Channels.newChannel(System.in);
WritableByteChannel dest = Channels.newChannel(System.out);
channelCopy1(source, dest);
// channelCopy2 (source, dest);
source.close();
dest.close(); } private static void channelCopy1(ReadableByteChannel src, WritableByteChannel dest)
throws IOException
{
ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024);
while (src.read(buffer) != -1)
{
// 切换为读状态
buffer.flip();
// 不能保证全部写入
dest.write(buffer);
// 释放已读数据的空间,等待数据写入
buffer.compact();
}
// 退出循环的时候,由于调用的是compact方法,缓冲区中可能还有数据
// 需要进一步读取
buffer.flip();
while (buffer.hasRemaining())
{
dest.write(buffer);
}
} private static void channelCopy2(ReadableByteChannel src, WritableByteChannel dest)
throws IOException
{
ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024);
while (src.read(buffer) != -1)
{
// 切换为读状态
buffer.flip();
// 保证缓冲区的数据全部写入
while (buffer.hasRemaining())
{
dest.write(buffer);
}
// 清除缓冲区
buffer.clear();
}
// 退出循环的时候,由于调用的是clear方法,缓冲区中已经没有数据,不需要进一步处理
} }

关闭通道

我们可以通过调用close()方法来关闭通道;

一个打开的通道代表与一个特定I/O服务的特定连接,并封装该连接的状态。当通道关闭时,这个连接会丢失,然后通道将不再连接任何东西。

可以通过isOpen()方法来判断通道是否打开,如果对关闭的通道进行读写等操作,会导致ClosedChannelException异常;

另外,如果一个通道实现了InterruptibleChannel接口,那么,当该通道上的线程被中断时,通道会被关闭,且该线程会抛出ClosedByInterruptException异常;

参考资料

《Java NIO》

Java NIO中的通道Channel(一)通道基础的更多相关文章

  1. Java NIO系列教程(五) 通道之间的数据传输

    在Java NIO中,如果两个通道中有一个是FileChannel,那你可以直接将数据从一个channel(译者注:channel中文常译作通道)传输到另外一个channel. transferFro ...

  2. java NIO中的buffer和channel

    缓冲区(Buffer):一,在 Java NIO 中负责数据的存取.缓冲区就是数组.用于存储不同数据类型的数据 根据数据类型不同(boolean 除外),提供了相应类型的缓冲区:ByteBufferC ...

  3. Java NIO学习笔记五 FileChannel(文件通道)

    Java NIO FileChannel Java NIO FileChannel是连接文件的通道.使用FileChannel,您可以从文件中读取数据和将数据写入文件.Java NIO FileCha ...

  4. 转:Java NIO系列教程(二) Channel

    Java NIO的通道类似流,但又有些不同: 既可以从通道中读取数据,又可以写数据到通道.但流的读写通常是单向的. 通道可以异步地读写. 通道中的数据总是要先读到一个Buffer,或者总是要从一个Bu ...

  5. Java NIO中核心组成和IO区别

    1.Java NIO核心组件 Java NIO中有很多类和组件,包括Channel,Buffer 和 Selector 构成了核心的API.其它组件如Pipe和FileLock是与三个核心组件共同使用 ...

  6. Java NIO中的Buffer 详解

    Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的.缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.这块内存被包装成NIO ...

  7. Java NIO中的缓冲区Buffer(一)缓冲区基础

    什么是缓冲区(Buffer) 定义 简单地说就是一块存储区域,哈哈哈,可能太简单了,或者可以换种说法,从代码的角度来讲(可以查看JDK中Buffer.ByteBuffer.DoubleBuffer等的 ...

  8. Java NIO(二) Channel

    Java NIO的通道类似流,但又有些不同: 既可以从通道中读取数据,又可以写数据到通道.但流的读写通常是单向的. 通道可以异步地读写. 通道中的数据总是要先读到一个Buffer,或者总是要从一个Bu ...

  9. Java NIO 三大组件之 Channel

    Java NIO 之 Channel 一.什么是Channel Channel用于源节点(例如磁盘)与目的节点的连接,它可以进行读取,写入,映射和读/写文件等操作. 在Java NIO中负责缓冲区中数 ...

  10. 转载Java NIO中的Files类的使用

    Java NIO中的Files类(java.nio.file.Files)提供了多种操作文件系统中文件的方法. Files.exists() Files.exits()方法用来检查给定的Path在文件 ...

随机推荐

  1. Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.

    Error starting ApplicationContext. To display the conditions report re-run your application with 'de ...

  2. APIView流程——请求方式分发

  3. ionic3使用第三方图标

    1.打开阿里图标库http://www.iconfont.cn 2.找到自己所需的图标,加入购物车(免费使用的) 3.打开购物车,点击右下角(下载代码) 4.解压文件,打开demo_unicode.h ...

  4. python基础之Day6

    一.元组 定义:t=(1,2,3,4) 总结:存多个值,值为任意类型 只有读的需求,没有改的需求 有序,不可变(元组里每个值对应的索引内存地址不能变) 在元素个数相同的情况下,元组比列表更节省空间 二 ...

  5. font-smoothing使用后字体看起来会更清晰舒服

    CSS3里面加入了一个“-webkit-font-smoothing”属性. 这个属性可以使页面上的字体抗锯齿,使用后字体看起来会更清晰舒服. 加上之后就顿时感觉页面小清晰了. 淘宝也在用哦! 它有三 ...

  6. 图解HTTP第五章

    与 HTTP 协作的 Web 服务器 一台 Web 服务器可搭建多个独立域名的 Web 网站,也可作为通信路径上的中转服务器提升传输效率. 1>用单台虚拟主机实现多个域名 HTTP/1.1 规范 ...

  7. qhfl-4 注册-登录-认证

    认证 任何的项目都需要认证,当用户输入了用户名和密码,验证通过,代表用户登录成功 那HTTP请求是无状态的,下次这个用户再请求,是不可能识别这个用户是否登录的 就要有自己的方式来实现这个认证,用户登录 ...

  8. hdu 1069 Monkey and Banana 【动态规划】

    题目 题意:研究人员要测试猴子的IQ,将香蕉挂到一定高度,给猴子一些不同大小的箱子,箱子数量不限,让猩猩通过叠长方体来够到香蕉. 现在给你N种长方体, 要求:位于上面的长方体的长和宽  要小于  下面 ...

  9. Hadoop 综合揭秘——HBase的原理与应用

    前言 现今互联网科技发展日新月异,大数据.云计算.人工智能等技术已经成为前瞻性产品,海量数据和超高并发让传统的 Web2.0 网站有点力不从心,暴露了很多难以克服的问题.为此,Google.Amazo ...

  10. ZKWeb网页框架1.7正式发布

    1.7.0更新的内容有 更新项目格式到新的csproj 更新项目模板 打开新创建的Asp.Net Core项目将需要VS 2017,Asp.Net和Owin项目仍可以用VS 2015 补上插件模板的P ...