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在文件 ...
随机推荐
- java编译时出现——注:使用了未经检查或不安全的操作。注:有关详细信息,请使用 -Xlint:unchecked 重新编译
网上说是泛型问题 private List<Product> products = new ArrayList<Product>(); 这种用法绝对没错!(因为是照着书写的)在 ...
- Xadmin显示视图
.display显示要设置的字段 1. 自定义样式类,显示出要显示的字段,在这个类中,也可以设置对应函数. list_display=[check,"title",delete]2 ...
- java【基础】日期操作
主要是date类,SimpleDateFormat类以及Calendar类的使用. date表示日期,simpleDateFormat 表示日期格式化,Calendar一般用来做时间的操作,比如加减天 ...
- linux就该这么学,第十天了
今天老师主要让要考试的提前预习课程了,提前预习, 今天讲了,防火墙,iptable.firewall-config,firewall-cmd 防火墙和网卡的配置方法,四种,1配置文件方法,主要开启 ...
- python3 第二十四章 - 函数式编程之Anonymous function(匿名函数)
匿名函数指一类无须定义标识符的函数或子程序.Python用lambda语法定义匿名函数,只需用表达式而无需申明.lambda语法的定义如下: lambda [arg1 [,arg2, ... argN ...
- .NET Core 中使用GB2312编码报错的问题
错误描述 环境 dotnet 2.1.4 现象 当代码中使用 System.Text.Encoding.GetEncoding("GB2312") //或者 System.Text ...
- boost--日期处理
1.timer 不同于系统函数的timer()一般生成一个定时器,boost中的timer是一个计时器,以秒为单位,最小精度为毫秒,使用需要包含头文件"boost\timer.hpp&quo ...
- std::string的拷贝赋值研究
说明:以下涉及的std::string的源代码摘自4.8.2版本.结论:std::string的拷贝复制是基于引用计数的浅拷贝,因此它们指向相同的数据地址. // std::string类定义type ...
- 【repost】H5的新特性及部分API详解
h5新特性总览 移除的元素 纯表现的元素: basefont.big.center.font等 对可用性产生负面影响的元素: frame.frameset.noframes 新增的API 语义: 能够 ...
- Crontab定时执行Oracle存储过程
Crontab定时执行Oracle存储过程 需求描述 我们有一个Oracle的存储过程,里面是每个月需要执行一下,生成报表,然后发送给业务部门,这一个功能我们有实现在系统的前台界面(如图1-1),但是 ...