1 Channel
通常来说NIO中的所有IO都是从 Channel(通道) 开始的。
从通道进行数据读取 :创建一个缓冲区,然后请求通道读取数据。
从通道进行数据写入 :创建一个缓冲区,填充数据,并要求通道写入数据。
2继承关系
这些类中只是声明了可操作的接口;主要是在不同的操作系统当中,其实际操作本地I/O和网络I/O在实现上会有根本性的差异,就拿Windows和Unix来说,两者的文件系统管理是不一致的(想了解三者I/O架构上的区别可参考Unix,Linux,Windows的IO架构)
1 Channel接口实现了Closeable接口,并且本身还定义isOpen()方法,标识所有的Channel都是可以被主动关闭
2 InterruptibleChannel接口声明了Channel是可以被中断的
3 SelectableChannel接口声明了Channel是可以被选择的(即支持Selector控制),而FileChannel是没有实现该接口的
4 WritableByteChannel和ReadableByteChannel接口分别提供了写操作和读操作的API,且是基于Buffer的
5 ScatteringByteChannel和GatheringByteChannel接口允许您委托操作系统来完成辛苦活:将读取到的数据分开存放到多个存储桶(bucket)或者将不同的数据区块合并成一个整体。这是一个巨大的成就,因为操作系统已经被高度优化来完成此类工作了。它节省了您来回移动数据的工作,也就避免了缓冲区拷贝和减少了您需要编写、调试的代码数量。其分别定义了write(ByteBuffer[] srcs, int offset, int length)和read(ByteBuffer[] dsts, int offset, int length)。SeekableByteChannel接口用于控制本地文件的positionNetworkChannel接口标识了该Channel是属于网络I/O
3 主要实现类
FileChannel:文件通道,用于文件的读和写,不支持非支持
DatagramChannel:用于 UDP 连接的接收和发送,服务端和客户端同一个
SocketChannel:把它理解为 TCP 连接通道,简单理解就是 TCP 客户端
ServerSocketChannel:TCP 对应的服务端,用于监听某个端口进来的请求
以下不常用的
SctpChannel SctpChannel是面向消息的连接传输,Sctp协议已数据块传输
SctpMultiChannel
SctpServerChannel
SinkChannel
SourceChannel
3.1 SocketChannel
3.2 ServerSocketChannel
3.3 FileChannel
可以使用 map映射,完成内存映射,提升大文件读写效率。
4 如何获取
本地io:
FileInputStreanm/FileOutputStream
RandomAccessFile
网络io:
Socket
ServerSocket
DatagramSocket
5 通道之间的数据传输
5.1、read&write
//将 Buffer 中数据写入 Channel
outChannel.write(buff)
//从 Channel 读取数据到 Buffer
inChannel.read(buff)
5.2 transferFrom
从源信道读取字节到这个通道的文件中。如果源通道的剩余空间小于 count 个字节,则所传输的字节数要小于请求的字节数。这种方法可能比从源通道读取并写入此通道的简单循环更有效率。
@param SRC 源通道
@param position 调动开始的文件内的位置,必须是非负的
@param count 要传输的最大字节数,必须是非负
@return 传输文件的大小(单位字节),可能为零,
public abstract long transferFrom(ReadableByteChannel src, long position, long count) throws IOException;
//复制图片,利用直接缓存区
public void test() throws Exception{
FileChannel inChannel = FileChannel.open(Paths.get("D:\\1.jpg"), StandardOpenOption.READ);
FileChannel outChannel = FileChannel.open(Paths.get("D:\\2.jpg"), StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE);
outChannel.transferFrom(inChannel,0, inChannel.size());
inChannel.close();
outChannel.close();
}
5.3 transferTo
将字节从这个通道的文件传输到给定的可写字节通道。
@param position 调动开始的文件内的位置,必须是非负的
@param count 要传输的最大字节数,必须是非负
@param target 目标通道
@return 传输文件的大小(单位字节),可能为零,
public abstract long transferTo(long position, long count, WritableByteChannel target) throws IOException;
//复制图片,利用直接缓存区
public void test2() throws Exception{
FileChannel inChannel = FileChannel.open(Paths.get("D:\\1.jpg"), StandardOpenOption.READ);
FileChannel outChannel = FileChannel.open(Paths.get("D:\\3.jpg"), StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE);
inChannel.transferTo(0, inChannel.size(), outChannel);
inChannel.close();
outChannel.close();
}
}
5 常用方法
int read(ByteBuffer dst) 从Channel到中读取数据到ByteBuffer
long read(ByteBuffer[] dsts) 将Channel到中的数据“分散”到ByteBuffer[]
int write(ByteBuffer src) 将ByteBuffer到中的数据写入到Channel
long write(ByteBuffer[] srcs) 将ByteBuffer[]到中的数据“聚集”到Channel
long position() 返回此通道的文件位置
FileChannel position(long p) 设置此通道的文件位置
long size() 返回此通道的文件的当前大小
FileChannel truncate(long s) 将此通道的文件截取为给定大小
void force(boolean metaData) 强制将所有对此通道的文件更新写入到存储设备中