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在文件 ...
随机推荐
- 735. Asteroid Collision彗星相撞后的消失数组
[抄题]: We are given an array asteroids of integers representing asteroids in a row. For each asteroid ...
- 491. Increasing Subsequences增长型序列
[抄题]: Given an integer array, your task is to find all the different possible increasing subsequence ...
- 拉普拉斯平滑处理 Laplace Smoothing
背景:为什么要做平滑处理? 零概率问题,就是在计算实例的概率时,如果某个量x,在观察样本库(训练集)中没有出现过,会导致整个实例的概率结果是0.在文本分类的问题中,当一个词语没有在训练样本中出现,该词 ...
- php Pthread 多线程 Worker
<?php //PHP 高级编程之多线程 http://www.netkiller.cn/journal/thread.php.html#idp57489856 //worker 是一个具有持久 ...
- BZOJ4381 : [POI2015]Odwiedziny / Luogu3591[POI2015]ODW - 分块+树剖
Solution 在步伐$pace$比较小的时候, 我们发现用前缀和直接维护会很快 而在$pace$比较大的时候, 则暴力往上跳会最优 设$blo= \sqrt{N}$ 若$pace<=blo$ ...
- jquery 表单校验
<link type="text/css" href="<%=basepath%>css/form/validate.css" rel=&qu ...
- Activity 重载方法 onStart和onResume、onPause和onStop的区别
Activity 重载方法 onStart和onResume.onPause和onStop的区别 首先了解Activity的四种状态 Running状态:一个新的Activity启动入栈后,它在屏幕最 ...
- Java:内部接口
1.什么是内部接口 内部接口也称为嵌套接口,即在一个接口内部定义另一个接口.举个例子,Entry接口定义在Map接口里面,如下代码: public interface Map { interface ...
- numpy版本查看以及升降
如题,参考:https://zhuanlan.zhihu.com/p/29026597 pip show numpy 查看numpy版本; pip install -U numpy==1.12.0, ...
- ABP框架系列之五十:(Swagger-UI-集成)
Introduction From it's web site: "....with a Swagger-enabled API, you get interactive documenta ...