如何快速使用NIO复制文件

    技术2025-08-23  9

    使用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(); }
    Processed: 0.010, SQL: 9