最重要的四种Channel
- FileChannel 文件通道,用于文件的读写
- SocketChannel tcp连接,客户端服务器都能用
- ServerSocketChannel tcp连接,用于服务器
- DatagramChannel UDP连接
FileChannel
FileChannel 只能工作在阻塞模式下
获取FileChannel:通过输入输出流或者RandomAccessFile 获取
- 通过 FileInputStream 获取的 channel 只能读
- 通过 FileOutputStream 获取的 channel 只能写
- 通过 RandomAccessFile 是否能读写根据构造 RandomAccessFile 时的读写模式决定
关闭FileChannel**:
channel 必须关闭,不过调用了 FileInputStream、FileOutputStream 或者 RandomAccessFile 的 close 方法会间接地调用 channel 的 close 方法
强制写入:
操作系统出于性能的考虑,会将数据缓存,不是立刻写入磁盘。可以调用 force(true) 方法将文件内容和元数据(文件的权限等信息)立刻写入磁盘
public static void copyFile1(String sourceFilePath,String targetFilePath){
var start = System.currentTimeMillis();
try {
@Cleanup FileInputStream fis = new FileInputStream(sourceFilePath);
@Cleanup FileOutputStream fos = new FileOutputStream(targetFilePath);
@Cleanup FileChannel inChannel = fis.getChannel();
@Cleanup FileChannel outChannel = fos.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024);
while(inChannel.read(buffer) != -1){
//切换为读模式
buffer.flip();
outChannel.write(buffer);
//清除buffer 变为写模式
buffer.clear();
}
//强制刷盘
outChannel.force(true);
} catch (FileNotFoundException e) {
System.out.println(" 源文件路径:" + sourceFilePath + "复制源文件不存在");
} catch (IOException e) {
System.out.println("文件复制异常" + e.getMessage());
}
var end = System.currentTimeMillis();
System.out.println("耗时:" + (end - start));
}
/**
*
* @param sourceFilePath
* @param targetFilePath
*/
public static void copyFile2(String sourceFilePath,String targetFilePath){
var start = System.currentTimeMillis();
try {
FileChannel sourceChannle = new FileInputStream(sourceFilePath).getChannel();
FileChannel targetChannle = new FileOutputStream(targetFilePath).getChannel();
long size = sourceChannle.size();
//表示还剩余多少字节没有传输
long left = size;
while (left > 0){
//底层会使用操作系统的零拷贝,一次最多传输2g的数据
left -= sourceChannle.transferTo(size - left,sourceChannle.size(),targetChannle);
}
targetChannle.force(true);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
var end = System.currentTimeMillis();
System.out.println("耗时:" + (end - start));
}
SocketChannel
NIO中涉及网元连接的通道有两个,一个是SocketChannel负责连接传输,另一个ServerSocketChannel负责连接的监听
ServerSocketChannel用于服务端,而SocketChannel同时应用于服务端和客户端,对于一个连接两端都有一个负责传输的SocketChannel传输通道。