博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java NIO中的通道Channel(一)通道基础
阅读量:5924 次
发布时间:2019-06-19

本文共 3386 字,大约阅读时间需要 11 分钟。

什么是通道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》

 

转载地址:http://btavx.baihongyu.com/

你可能感兴趣的文章
shell脚本实现scp文件传输
查看>>
Tengine ngx_http_upstream_check_module 健康功能检测使用
查看>>
零停重启程序工具Huptime研究
查看>>
lzg_ad: WinXP及Win2003下文件内容搜索不到的解决方案
查看>>
关于端口聚合或端口聚合称呼的误区
查看>>
Office2010新功能:方便快捷的屏幕截图
查看>>
MyEclipse 中配置struts2.2.1的方法
查看>>
工作笔记-RTX软件用友OA冲突解决
查看>>
数据库设计中一个矛盾:数据库外键 你用还是不用(2) 继续....
查看>>
直播源码部署直播软件系统搭建!
查看>>
MDaemon升级用户数之后 仍然无法创建新账号
查看>>
Hibernate4.0之HibernateSessionFactory源码详解
查看>>
Windows NT 内核基本结构
查看>>
DataGrid与SQL Server 2000数据绑定
查看>>
linux 搭建ftp服务器
查看>>
Jenkins的持续集成及自动化部署在测试和生产环境中的运用系列
查看>>
Microsoft uaa bus driver for high definition audio
查看>>
Spring(26)——PathMatchingResourcePatternResolver
查看>>
耦合_wiki
查看>>
JavaScript -- 条件语句
查看>>