java实现文件拷贝的七种方式

文章目录

        • 1. 通过字节流实现文件的拷贝
        • 2. 通过字符流实现文件拷贝
        • 3. 通过字节缓冲流实现文件拷贝
        • 4. 通过字符缓冲流拷贝文件
        • 5. 通过JAVA NIO 非直接缓冲区拷贝文件
        • 6. 通过JAVA NIO 直接缓冲区拷贝文件
        • 7. 通过JAVA NIO 通道传输拷贝文件
        • 使用示例

1. 通过字节流实现文件的拷贝

  /**
     * 通过字节流实现文件的拷贝
     * @param sourcePath 源文件路径
     * @param targetPath 目标文件路径
     */
    public static void copyFileByStream(String sourcePath,String targetPath){
        //源文件路径
        File source = new File(sourcePath);
        //目标文件路径
        File target = new File(targetPath);

        //如果源文件不存在则不能拷贝
        if(!source.exists()){
            return;
        }
        //如果目标文件目录不存在则创建
        if(!target.getParentFile().exists()){
            target.getParentFile().mkdirs();
        }

        try {
            //实现文件的拷贝
            InputStream inputStream = new FileInputStream(source);
            OutputStream outputStream = new FileOutputStream(target);
            int temp = 0;
            //每次读取1024个字节
            byte[] data = new byte[1024];
            //将每次读取的数据保存到字节数组里面,并且返回读取的个数
            while ((temp = inputStream.read(data)) != -1){
                //输出数组
                outputStream.write(data,0,temp);
            }

            inputStream.close();
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

2. 通过字符流实现文件拷贝

使用字符流只能拷贝文本文件

    /**
     * 通过字符流实现文件的拷贝
     *
     * @param sourcePath 源文件路径
     * @param targetPath 目标文件路径
     */
    public static void copyFileByReaderAndWriter(String sourcePath, String targetPath) {
        //源文件路径
        File source = new File(sourcePath);
        //目标文件路径
        File target = new File(targetPath);

        //如果源文件不存在则不能拷贝
        if (!source.exists()) {
            return;
        }
        //如果目标文件目录不存在则创建
        if (!target.getParentFile().exists()) {
            target.getParentFile().mkdirs();
        }

        FileReader in = null;
        FileWriter out = null;
        try {
            //字符输入流和字符输出流
            in = new FileReader(source);
            out = new FileWriter(target);

            char[] c = new char[1024];
            int temp = 0;
            //每次读取1024个字符
            while ((temp = in.read(c)) != -1) {
                //输出到文件
                out.write(c, 0, temp);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭流
            try {
                if (in != null) {
                    in.close();
                }
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

3. 通过字节缓冲流实现文件拷贝

/**
     * 通过字节缓冲流实现文件的拷贝
     *
     * @param sourcePath 源文件路径
     * @param targetPath 目标文件路径
     */
    public static void copyFileByBuffered(String sourcePath, String targetPath){
        //源文件路径
        File source = new File(sourcePath);
        //目标文件路径
        File target = new File(targetPath);

        //如果源文件不存在则不能拷贝
        if (!source.exists()) {
            return;
        }
        //如果目标文件目录不存在则创建
        if (!target.getParentFile().exists()) {
            target.getParentFile().mkdirs();
        }

        InputStream in = null;
        OutputStream out = null;
        try {
            //字节缓冲输入流和字节缓冲输出流
            in = new BufferedInputStream(new FileInputStream(source));
            out = new BufferedOutputStream(new FileOutputStream(target));

            byte[] b = new byte[1024];
            int temp = 0;
            //每次读取一个1024的字节数组
            while((temp = in.read(b)) != -1){
                //输出到文件
                out.write(b,0,temp);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //关闭流
            try {
                if (in != null) {
                    in.close();
                }
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

4. 通过字符缓冲流拷贝文件

字符缓冲流只能读取文本文件

 /**
     * 通过字符缓冲流实现文件的拷贝
     *
     * @param sourcePath 源文件路径
     * @param targetPath 目标文件路径
     */
    public static void copyFileByBufferedChar(String sourcePath, String targetPath){
        //源文件路径
        File source = new File(sourcePath);
        //目标文件路径
        File target = new File(targetPath);

        //如果源文件不存在则不能拷贝
        if (!source.exists()) {
            return;
        }
        //如果目标文件目录不存在则创建
        if (!target.getParentFile().exists()) {
            target.getParentFile().mkdirs();
        }

        BufferedReader in = null;
        BufferedWriter out = null;

        try {
            //字符缓冲输入流和字符缓冲输出流
            in = new BufferedReader(new FileReader(source));
            out = new BufferedWriter(new FileWriter(target));

            //读取文件(每次读取一行)
            String temp = null;
            while((temp = in.readLine()) != null){
                //输出到文件
                out.write(temp);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //关闭流
            try {
                if (in != null) {
                    in.close();
                }
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

5. 通过JAVA NIO 非直接缓冲区拷贝文件

   /**
     * 通过JAVA NIO 非直接缓冲区拷贝文件
     *
     * @param sourcePath 源文件路径
     * @param targetPath 目标文件路径
     */
    public static void copyFileByChannel(String sourcePath, String targetPath) {
        FileChannel outChannel = null;
        FileChannel inChannel = null;

        FileInputStream fis = null;
        FileOutputStream fos = null;

        try {
            fis = new FileInputStream(sourcePath);
            fos = new FileOutputStream(targetPath);

            //获取通道
            inChannel = fis.getChannel();
            outChannel = fos.getChannel();

            //分配指定大小的缓冲区
            ByteBuffer buf = ByteBuffer.allocate(1024);

            while (inChannel.read(buf) != -1) {
                //转换为读取数据模式
                buf.flip();
                //写入到磁盘
                outChannel.write(buf);
                //清空缓冲区
                buf.clear();
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭流
            try {
                if (outChannel != null) {
                    outChannel.close();
                }
                if (inChannel != null) {
                    inChannel.close();
                }
                if (fis != null) {
                    fis.close();
                }
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

6. 通过JAVA NIO 直接缓冲区拷贝文件

/**
     * 通过JAVA NIO 直接缓冲区拷贝文件(内存映射文件)
     *
     * @param sourcePath 源文件路径
     * @param targetPath 目标文件路径
     */
    public static void copyFileByChannelBufferd(String sourcePath, String targetPath) {
        FileChannel inChannel = null;
        FileChannel outChannel = null;
        try {
            //获取通道,StandardOpenOption.READ表示可读,StandardOpenOption.WRITE表示可写,StandardOpenOption.CREATE表示可以创建
            inChannel = FileChannel.open(Paths.get(sourcePath), StandardOpenOption.READ);
            outChannel = FileChannel.open(Paths.get(targetPath), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);

            //创建内存映射文件
            MappedByteBuffer inMapped = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());
            MappedByteBuffer outMapped = outChannel.map(FileChannel.MapMode.READ_WRITE, 0, inChannel.size());

            //直接操作内存映射文件
            byte[] buf = new byte[inMapped.limit()];
            inMapped.get(buf);
            outMapped.put(buf);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭流
            try {
                if (outChannel != null) {
                    outChannel.close();
                }
                if (inChannel != null) {
                    inChannel.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

7. 通过JAVA NIO 通道传输拷贝文件

方式一

 /**
     *  通过JAVA NIO 通道传输拷贝文件
     *
     * @param sourcePath 源文件路径
     * @param targetPath 目标文件路径
     */
    public static void copyFileByChannelTransfer(String sourcePath, String targetPath) {
        FileChannel inChannel = null;
        FileChannel outChannel = null;
        try {
            //获取通道
            inChannel = FileChannel.open(Paths.get(sourcePath), StandardOpenOption.READ);
            outChannel = FileChannel.open(Paths.get(targetPath),StandardOpenOption.WRITE,StandardOpenOption.READ,StandardOpenOption.CREATE);

            inChannel.transferTo(0,inChannel.size(),outChannel);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关闭流
            try {
                if (outChannel != null) {
                    outChannel.close();
                }
                if (inChannel != null) {
                    inChannel.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

方式二

 /**
     *  通过JAVA NIO 通道传输拷贝文件
     *
     * @param sourcePath 源文件路径
     * @param targetPath 目标文件路径
     */
    public static void copyFileByChannelTransfer2(String sourcePath, String targetPath) {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        FileChannel inChannel = null;
        FileChannel outChannel = null;
        try {
            fis = new FileInputStream(sourcePath);
            fos = new FileOutputStream(targetPath);

            //获取通道
            inChannel = fis.getChannel();
            outChannel = fos.getChannel();

            inChannel.transferTo(0,inChannel.size(),outChannel);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关闭流
            try {
                if (outChannel != null) {
                    outChannel.close();
                }
                if (inChannel != null) {
                    inChannel.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

使用示例

        String source = "e:\\demo\\纵天神帝.txt";
        String target = "e:\\demo\\";
        long time1 = System.currentTimeMillis();
        copyFileByStream(source, target + "1.txt");
        System.out.println("通过字节流实现文件的拷贝耗时:" + (System.currentTimeMillis() - time1));

        long time2 = System.currentTimeMillis();
        copyFileByReaderAndWriter(source, target + "2.txt");
        System.out.println("通过字符流实现文件的拷贝耗时:" + (System.currentTimeMillis() - time2));

        long time3 = System.currentTimeMillis();
        copyFileByBuffered(source, target + "3.txt");
        System.out.println("通过字节缓冲流实现文件的拷贝耗时:" + (System.currentTimeMillis() - time3));

        long time4 = System.currentTimeMillis();
        copyFileByBufferedChar(source, target + "4.txt");
        System.out.println("通过字符缓冲流实现文件的拷贝耗时:" + (System.currentTimeMillis() - time4));

        long time5 = System.currentTimeMillis();
        copyFileByChannel(source, target + "5.txt");
        System.out.println("通过JAVA NIO通道(非直接缓冲区)实现文件的拷贝耗时:" + (System.currentTimeMillis() - time5));

        long time6 = System.currentTimeMillis();
        copyFileByChannelBufferd(source, target + "6.txt");
        System.out.println("通过JAVA NIO通道(直接缓冲区)实现文件的拷贝耗时:" + (System.currentTimeMillis() - time6));

        long time7 = System.currentTimeMillis();
        copyFileByChannelTransfer(source, target + "7.txt");
        System.out.println("通过JAVA NIO通道传输实现文件的拷贝耗时:" + (System.currentTimeMillis() - time7));

        long time8 = System.currentTimeMillis();
        copyFileByChannelTransfer(source, target + "8.txt");
        System.out.println("通过JAVA NIO通道传输2实现文件的拷贝耗时:" + (System.currentTimeMillis() - time8));

通过测试发现,使用JAVA NIO通道传输、JAVA NIO通道直接缓冲区以及字节缓冲流拷贝文件效率最高

你可能感兴趣的:(java)