Java NIO中的通道Channel(一)通道基础
什么是通道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(一)通道基础的更多相关文章
- Java NIO系列教程(五) 通道之间的数据传输
在Java NIO中,如果两个通道中有一个是FileChannel,那你可以直接将数据从一个channel(译者注:channel中文常译作通道)传输到另外一个channel. transferFro ...
- java NIO中的buffer和channel
缓冲区(Buffer):一,在 Java NIO 中负责数据的存取.缓冲区就是数组.用于存储不同数据类型的数据 根据数据类型不同(boolean 除外),提供了相应类型的缓冲区:ByteBufferC ...
- Java NIO学习笔记五 FileChannel(文件通道)
Java NIO FileChannel Java NIO FileChannel是连接文件的通道.使用FileChannel,您可以从文件中读取数据和将数据写入文件.Java NIO FileCha ...
- 转:Java NIO系列教程(二) Channel
Java NIO的通道类似流,但又有些不同: 既可以从通道中读取数据,又可以写数据到通道.但流的读写通常是单向的. 通道可以异步地读写. 通道中的数据总是要先读到一个Buffer,或者总是要从一个Bu ...
- Java NIO中核心组成和IO区别
1.Java NIO核心组件 Java NIO中有很多类和组件,包括Channel,Buffer 和 Selector 构成了核心的API.其它组件如Pipe和FileLock是与三个核心组件共同使用 ...
- Java NIO中的Buffer 详解
Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的.缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.这块内存被包装成NIO ...
- Java NIO中的缓冲区Buffer(一)缓冲区基础
什么是缓冲区(Buffer) 定义 简单地说就是一块存储区域,哈哈哈,可能太简单了,或者可以换种说法,从代码的角度来讲(可以查看JDK中Buffer.ByteBuffer.DoubleBuffer等的 ...
- Java NIO(二) Channel
Java NIO的通道类似流,但又有些不同: 既可以从通道中读取数据,又可以写数据到通道.但流的读写通常是单向的. 通道可以异步地读写. 通道中的数据总是要先读到一个Buffer,或者总是要从一个Bu ...
- Java NIO 三大组件之 Channel
Java NIO 之 Channel 一.什么是Channel Channel用于源节点(例如磁盘)与目的节点的连接,它可以进行读取,写入,映射和读/写文件等操作. 在Java NIO中负责缓冲区中数 ...
- 转载Java NIO中的Files类的使用
Java NIO中的Files类(java.nio.file.Files)提供了多种操作文件系统中文件的方法. Files.exists() Files.exits()方法用来检查给定的Path在文件 ...
随机推荐
- ES6 Iterator
不同数据集合怎么用统一的方式读取 可以用for...of循环了
- CentOS7 开启网卡,设置开机启用网卡
默认centos和redhat7都是不启用有线网卡的,要么手动开启,要么安装时直接启用(安装时启用网卡和指定IP最省事)! 一 .临时启用网卡,关机或重启后,网络不会自动开启1.使用命令 ip add ...
- Python开发——文件操作
文件的读取 http://www.cnblogs.com/linhaifeng/articles/5984922.html
- 什么叫做API?看完你就理解了
阅读编程资料时经常会看到API这个名词,网上各种高大上的解释估计放倒了一批初学者.初学者看到下面这一段话可能就有点头痛了. API(Application Programming Interface, ...
- 20172306《Java程序设计与数据结构》第一周总结
20172306<Java程序设计>第一周学习总结 教材学习内容总结 本周主要学习<Android和Java>书中的第二十三章和第二十六章. 第二十三章:Android简介 A ...
- I/O dempo
标准读取写入 package io_stream; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; i ...
- margin和padding的用法与区别--以及bug处理方式
margin和padding的用法: (1)padding (margin) -left:10px; 左内 (外) 边距(2)padding (margin) -right:10px; 右内 (外 ...
- jenkins可选插件为空的解决方式
我是安装的jenkins,文件名字是这个jenkins.msi,点finish安装完成,然后浏览器就自动打开了jenkins页面,输入密码后,便进入了如下页面 之后我是选择的跳过插件安装,在可选插件里 ...
- 2019.02.14 codechef Chef at the Food Fair(线段树+泰勒展开)
传送门 题意:现在有nnn个位置,每个位置上有一个值aia_iai. 要求支持如下两种操作: 区间乘vvv 求区间的(1−ai)(1-a_i)(1−ai)之积 思路: 考虑转换式子: Ans=∏i ...
- [smf]论坛实现编辑器附件插入的插件
smf论坛代码的相关介绍,可以参见博客园的其他文章,这里不再详细说明了. 插件功能: 在帖子里的任何位置插入附件图片. 关于安装: 该插件已经经过“维尼熊的百宝箱”的修改,在新版本SMF 2.0.14 ...