【Java】文件复制的各种姿势

本文介绍了五种Java中复制文件的方法,包括传统的BIO方式、NIO Buffer方式、NIO Channel方式、NIO文件内存映射方式及使用JDK7提供的Files类进行文件复制。每种方法都附带了具体的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

下面讲解一下Java中复制文件的各种姿势。

1. BIO

第一种是传统IO操作方式,即输入输出流配合,一个读一个写,相对简单

public static void copyFile(String s, String d) {
        int readPerSize = 1024 * 1024;
        try (FileInputStream in = new FileInputStream(s);
             FileOutputStream out = new FileOutputStream(d);) {
            byte[] buffer = new byte[readPerSize];
            int len = 0;
            while ((len = in.read(buffer)) > 0) {
                out.write(buffer, 0, len);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

2. NIO Buffer

  • 从 FileInputStream 获取 FileChannel;
  • 创建 Buffer(ByteBuffer的allocateallocateDirect方法,一个是堆内存,一个是本地内存);
  • 将数据从 FileChannel 读到 Buffer 中,并通过返回值大小判断Buffer大小;
  • 同时切换读模式 filp,然后写入FileOutputStream的 FileChannel中;
  • 缓存清除;
  • FileChannel关闭;
    public static void copyFileByByteBuffer(String source, String dest, ByteBuffer buffer) {
        try (FileInputStream in = new FileInputStream(source);
             FileOutputStream out = new FileOutputStream(dest);
        ) {
            FileChannel inChannel = in.getChannel();
            FileChannel outChannel = out.getChannel();
            int size = inChannel.read(buffer);
            while (size > -1) {
                buffer.flip();
                outChannel.write(buffer);
                buffer.clear();
                size = inChannel.read(buffer);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            buffer.clear();
        }
    }

3. NIO Channel

Buffer方式类似,但是复制过程通过outChanneltransferFrominChanneltransferTo实现

    public static void copyFileByChannel(String s, String d, ByteBuffer buffer) {
        int readPerSize = 1024 * 1024;
        try (FileInputStream in = new FileInputStream(s);
             FileOutputStream out = new FileOutputStream(d);){
            FileChannel inChannel = in.getChannel();
            FileChannel outChannel = out.getChannel();
            int pos = 0;
            // 也可以通过 inChannel 的 transferTo 去写入
            while (pos < inChannel.size()) {
                pos += outChannel.transferFrom(inChannel, pos, readPerSize);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

4. NIO 文件内存映射

    public static void copyFileByDirectBuffer(String s, String d) {
        int readPerSize = 1024 * 1024;
        try {
            FileChannel inChannel = new RandomAccessFile(s,"r").getChannel();
            FileChannel outChannel = new RandomAccessFile(d,"rw").getChannel();
            long fileSize = inChannel.size();
            int pos = 0;
            while (pos < fileSize) {
                long copyFileSize = Math.min((fileSize-pos),readPerSize);
                //得到的是DirectByteBuffer
                MappedByteBuffer byteBuffer = outChannel.map(FileChannel.MapMode.READ_WRITE,pos,copyFileSize);
                inChannel.read(byteBuffer);
                pos += byteBuffer.position();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

5. 终极大招

JDK7提供了一个文件操作的工具类 —- Files

File提供了诸如:copy / delete / move / read 等各种静态方法,对文件的操作进一步封装。

有了这些方法,就不需要我们手动的去操作输入输出流,读写操作等,实乃良心。

Files.copy(Paths.get("E:\\Book\\ Vim实用技巧.pdf"),Paths.get("D:\\Vim实用技巧.pdf"));

引用

《Java特种兵·上册》 第四章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值