使用NIO复制文件
利用NIO中的Channel(通道)这一特性实现对文件快速复制
情况一:如果文件大小在2GB以下
这个时候可以使用MappedByteBuffer直接把文件映射到内存中,在内存中实现复制,然后再映射到目的地,这样就可以将硬盘的读写转移到了内存中的读写,提高读写效率
public static void main(String[] args) throws Exception{
//java.io.RandomAccessFile类,可以设置读、写模式的IO流类。
//"r"表示:只读--输入流,只读就可以。
RandomAccessFile randomAccessFile1 = new RandomAccessFile("被复制的文件的路径","r");
//"rw"表示:读、写--输出流,需要读、写。
RandomAccessFile randomAccessFile2 = new RandomAccessFile("复制后的文件要存储的路劲","rw");
// 获得FileChannel管道对象
FileChannel fileChannel1 = randomAccessFile1.getChannel();
FileChannel fileChannel2 = randomAccessFile2.getChannel();
// 获取文件的大小
long size = fileChannel1.size();
// 直接把硬盘中的文件映射到内存中
MappedByteBuffer mappedByteBuffer1 = fileChannel1.map(FileChannel.MapMode.READ_ONLY, 0, size);
MappedByteBuffer mappedByteBuffer2 = fileChannel2.map(FileChannel.MapMode.READ_WRITE, 0, size);
// 循环读取数据
for (long i = 0; i < size; i++) {
// 读取字节
byte byt = mappedByteBuffer1.get();
// 保存到第二个数组中
mappedByteBuffer2.put(byt);
}
// 释放资源
fileChannel2.close();
fileChannel1.close();
randomAccessFile2.close();
randomAccessFile1.close();
}
情况二:要复制的文件大小超过2GB
这种情况,MappedByteBuffer不能直接将文件映射到内存,所以就需要进行分块操作,将大文件分为几次进行映射
public static void main(String[] args) throws Exception {
/*
使用MappedByteBuffer复制超过2GB的文件
*/
// 创建RandomAccessFile对象
RandomAccessFile randomAccessFile1 = new RandomAccessFile("day14\\aaa\\123.jpg", "r");
RandomAccessFile randomAccessFile2 = new RandomAccessFile("day14\\bbb\\123Copy.jpg", "rw");
// 创建管道对象
FileChannel fileChannel1 = randomAccessFile1.getChannel();
FileChannel fileChannel2 = randomAccessFile2.getChannel();
// 如果文件大小超过2GB,则需要分块拷贝
// 获取文件的总大小
long size = fileChannel1.size();
// 定义每次文件要拷贝的大小
long everySize = 1024 * 1024 * 512;
// 获取需要循环的次数
long count = size % everySize == 0 ? size / everySize : size / everySize + 1;
for (long i = 0; i < count; i++) {
// 定义每次开始的位置
long startSize = i * everySize;
// 定义每次要拷贝的大小
long trueSize = size - startSize >= everySize ? everySize : size - startSize;
// 创建映射缓冲数组
MappedByteBuffer map1 = fileChannel1.map(FileChannel.MapMode.READ_ONLY, startSize, trueSize);
MappedByteBuffer map2 = fileChannel2.map(FileChannel.MapMode.READ_WRITE, startSize, trueSize);
// 循环读取数据
for (long j = 0; j < trueSize; j++) {
// 读数据
byte b = map1.get();
// 写数据
map2.put(b);
}
}
// 关闭流,释放资源
fileChannel2.close();
fileChannel1.close();
randomAccessFile2.close();
randomAccessFile1.close();
}