NIO之Channel通道(一)-Channel、FileChannel
Channel叫做通道,用于I/O操作的连接。与Stream不同,可以双向的进行数据通信。
Channel相关的的类和接口都存放于以下两个包中:
- java.nio.channels:定义了各种通道,这些通道表示到能够执行 I/O 操作的实体(如文件和套接字)的连接;定义了用于多路复用的、非阻塞 I/O 操作的选择器。
- java.nio.channels.spi:用于 java.nio.channels 包的服务提供程序类。
1 获取通道的方式
获取通道有以下6种方式。
1.1 getChannel()
Java针对支持通道的类提供了getChannel()方法:
- 本地IO:FileInputstream、FileOutputstream、RandomAccessFile。
- 网络IO:Socket、ServerSocket、DatagramSockte。
1.2 open()
在JDK1.7中的NIO.2针对各个通道提供了静态方法open()
1.3 newByteChannel()
在JKD1.7中的NIO.2的Files工具类的newByteChannel()
1.4 数据传输
通道之间的数据传输:
- transferFrom()
- transferTo()
1.5 分散与聚集
分散(Scatter)与聚集(Gather):
- 分散读取(Scattering Reads):将通道中的数据分散到多个缓冲区。
- 聚集写入(Gathering Writes):将多个缓冲区的数据聚集到通道中。
1.6 字符集
字符集:Charset
- 编码:字符串→字符数组
- 解码:字符数组→字符串
2 Channel
Channel是一个接口,以下为其实现类和子类继承结构。
代码语言:javascript复制Channel
|-AbstractInterruptibleChannel
| |- FileChannel
| |- FileChannelImpl
|- ReadableByteChannelImpl
| |- SelectableChannel
| |- AbstractSelectableChannel
| |- ServerSocketChannel
| |- SocketChannel
| |- DatagramChannel
2.1 重要方法
此接口只有两个方法,分别如下:
2.1.1 close()
关闭此通道。
2.1.2 isOpen()
判断此通道是否处于打开状态。
3 FileChannel
主要用于文件的读写,可以从磁盘上读取文件,也可以向磁盘上写入文件。
这是一个抽象类,此类继承AbstractInterruptibleChannel,实现了SeekableByteChannel、GatheringByteChannel、ScatteringByteChannel三个接口。
创建FileChannel对象,底层调用的是FileChannelImpl的构造函数。
3.1 RandomAccessFile模式
RandomAccessFile的模式有四种:r、rw、rws、rwd。
- r:只能读。
- rw:可读,可写。
- rws:可读可写,每次改动都强制保存,在写入的时候会将操作系统对该文件的元数据也一起刷盘,体现就是文件的更新时间会修改。
- rwd:可读,可写,每次改动都强制保存。
3.2 重要方法
3.2.1 open()
此方法通过文件系统创建一个FileChannel。
此方法有两个重载如下:
- open(Path, Set<? extends OpenOption>, FileAttribute<?>...)
- open(Path, OpenOption...)
3.2.2 read()
读取缓冲区中的内容,重载的方法大部分都是抽象方法,等待子类进行实现。
重载方法如下:
- read(ByteBuffer)
- read(ByteBuffer, long)
- read(ByteBuffer[], int, int)
- read(ByteBuffer[])
3.2.3 write()
将缓冲区中的内容写出,重载的方法大部分都是抽象方法,等待子类进行实现。
重载方法如下:
- write(ByteBuffer)
- write(ByteBuffer, long)
- write(ByteBuffer[], int, int)
- write(ByteBuffer[])
3.2.4 position()
返回这个通道中文件的当前位置。
3.2.5 position(long)
设置一个通道中文件的当前位置。
3.2.6 size()
返回当前通道中,文件的大小。
3.2.7 truncate(long)
将此通道中的文件截断为指定的大小。
3.2.8 force(boolean)
将通道内的更新内容强制写入存储设备中。
3.2.9 transferTo(long, long, WritableByteChannel)
将文件中的内容传送到写通道中。
3.2.10 transferFrom(ReadableByteChannel, long, long)
将通道中的内容传送到读通道中。
3.2.11 lock()
获取此通道给定的锁。有两个重载的方法。
- lock(long, long, boolean)
- lock()
3.2.12 tryLock()
尝试获取此通道给定的锁,有两个重载方法。
- tryLock(long, long, boolean)
- tryLock()
3.3 案例
代码语言:javascript复制import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
public static void fctest(String file, String mod) throws Exception {
// 打开文件
RandomAccessFile raf = new RandomAccessFile(file, mod);
// 获取一个通道
FileChannel fc = raf.getChannel();
// 创建缓冲区
ByteBuffer buffer = ByteBuffer.allocate(16);
// 存入缓冲区数据
buffer.put("FileChannelTest".getBytes(StandardCharsets.UTF_8));
// 将缓冲区切换成读模式
buffer.flip();
// 将缓冲区中的数据通过通道写出
fc.write(buffer);
// 清空缓冲区
buffer.clear();
// 读取缓冲区数据
fc.read(buffer);
fc.close();
raf.close();
}