今天一个同事问我文件复制的问题,他一个100M的文件复制的指定目录下竟然成了1G多,吓我一跳,后来看了他的代码发现是自己通过字节流复制的,定义的字节数组很大,导致复制后目标文件非常大,其实就是空行等一些无效空间。我也是很少用这种方式拷贝问价,大多数用Apache提供的commons-io中的FileUtils,后来在网上查了下,发现还有其他的方式,效率更高,所以在此整理一下,也是自己的一个学习。

1. 使用FileStreams复制

比较经典的一个代码,使用FileInputStream读取文件A的字节,使用FileOutputStream写入到文件B。

public static void copy(String source, String dest, int bufferSize) {
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(new File(source));
out = new FileOutputStream(new File(dest)); byte[] buffer = new byte[bufferSize];
int len; while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
} catch (Exception e) {
Log.w(TAG + ":copy", "error occur while copy", e);
} finally {
safelyClose(TAG + ":copy", in);
safelyClose(TAG + ":copy", out);
}
}
2.

2、使用FileChannel

Java NIO包括transferFrom方法,根据文档应该比文件流复制的速度更快。

public static void copyNio(String source, String dest) {
FileChannel input = null;
FileChannel output = null; try {
input = new FileInputStream(new File(from)).getChannel();
output = new FileOutputStream(new File(to)).getChannel();
output.transferFrom(input, 0, input.size());
} catch (Exception e) {
Log.w(TAG + "copyNio", "error occur while copy", e);
} finally {
safelyClose(TAG + "copyNio", input);
safelyClose(TAG + "copyNio", output);
}
} 3、 使用Apache Commons IO复制
Appache Commons IO 提供了一个FileUtils.copyFile(File from, File to)方法用于文件复制,如果项目里使用到了这个类库,使用这个方法是个不错的选择。
它的内部也是使用Java NIO的FileChannel实现的。
commons-io的路径:http://commons.apache.org/proper/commons-io/javadocs/api-release/index.html。里面还有很多实用的方法,如拷贝目录、拷贝指定格式文件等。
private static void  copyFileByApacheCommonsIO(File source, File dest) throws IOException {
FileUtils.copyFile(source, dest);
}
4、使用Java7的Files类复制
private static void copyFileUsingJava7Files(File source, File dest) throws IOException {
Files.copy(source.toPath(), dest.toPath());
}
我没有亲测,找了下网友的测试程序和输出,性能数据供大家参考(来源:https://www.jb51.net/article/70412.htm)
import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.nio.channels.FileChannel;

import java.nio.file.Files;

import org.apache.commons.io.FileUtils;

public class CopyFilesExample {
  public static void main(String[] args) throws InterruptedException,

      IOException {

    File source = new File("C:\\Users\\nikos7\\Desktop\\files\\sourcefile1.txt");

    File dest = new File("C:\\Users\\nikos7\\Desktop\\files\\destfile1.txt");

  

    // copy file using FileStreams

    long start = System.nanoTime();

    long end;

    copyFileUsingFileStreams(source, dest);

    System.out.println("Time taken by FileStreams Copy = "

        + (System.nanoTime() - start));
 
    // copy files using java.nio.FileChannel

    source = new File("C:\\Users\\nikos7\\Desktop\\files\\sourcefile2.txt");

    dest = new File("C:\\Users\\nikos7\\Desktop\\files\\destfile2.txt");

    start = System.nanoTime();

    copyFileUsingFileChannels(source, dest);

    end = System.nanoTime();

    System.out.println("Time taken by FileChannels Copy = " + (end - start));
    // copy file using Java 7 Files class

    source = new File("C:\\Users\\nikos7\\Desktop\\files\\sourcefile3.txt");

    dest = new File("C:\\Users\\nikos7\\Desktop\\files\\destfile3.txt");

    start = System.nanoTime();

    copyFileUsingJava7Files(source, dest);

    end = System.nanoTime();

    System.out.println("Time taken by Java7 Files Copy = " + (end - start));

    // copy files using apache commons io

    source = new File("C:\\Users\\nikos7\\Desktop\\files\\sourcefile4.txt");

    dest = new File("C:\\Users\\nikos7\\Desktop\\files\\destfile4.txt");

    start = System.nanoTime();

    copyFileUsingApacheCommonsIO(source, dest);

    end = System.nanoTime();

    System.out.println("Time taken by Apache Commons IO Copy = "

        + (end - start));
  }

  private static void copyFileUsingFileStreams(File source, File dest)

      throws IOException {

    InputStream input = null;

    OutputStream output = null;

    try {

      input = new FileInputStream(source);

      output = new FileOutputStream(dest);

      byte[] buf = new byte[1024];

      int bytesRead;

      while ((bytesRead = input.read(buf)) > 0) {

        output.write(buf, 0, bytesRead);

      }

    } finally {

      input.close();

      output.close();

    }

  }

  private static void copyFileUsingFileChannels(File source, File dest)

      throws IOException {

    FileChannel inputChannel = null;

    FileChannel outputChannel = null;

    try {

      inputChannel = new FileInputStream(source).getChannel();

      outputChannel = new FileOutputStream(dest).getChannel();

      outputChannel.transferFrom(inputChannel, 0, inputChannel.size());

    } finally {

      inputChannel.close();

      outputChannel.close();

    }

  }

  private static void copyFileUsingJava7Files(File source, File dest)

      throws IOException {

    Files.copy(source.toPath(), dest.toPath());

  }

  private static void copyFileUsingApacheCommonsIO(File source, File dest)

      throws IOException {

    FileUtils.copyFile(source, dest);

  }
}

输出:

Time taken by FileStreams Copy = 127572360

Time taken by FileChannels Copy = 10449963

Time taken by Java7 Files Copy = 10808333

Time taken by Apache Commons IO Copy = 17971677
 

java中文件复制的4种方式的更多相关文章

  1. java中数组复制的两种方式

    在java中数组复制有两种方式: 一:System.arraycopy(原数组,开始copy的下标,存放copy内容的数组,开始存放的下标,需要copy的长度); 这个方法需要先创建一个空的存放cop ...

  2. Java实现文件复制的四种方式

    背景:有很多的Java初学者对于文件复制的操作总是搞不懂,下面我将用4中方式实现指定文件的复制. 实现方式一:使用FileInputStream/FileOutputStream字节流进行文件的复制操 ...

  3. Java中数组复制的几种方式以及数组合并

    1.Object.clone() 简单直接,只能对源数组完整地复制 2.Arrays.copyOf(T[] original, int newLength) 可以只复制源数组中部分元素,但复制的起始位 ...

  4. Java中HashMap遍历的两种方式

    Java中HashMap遍历的两种方式 转]Java中HashMap遍历的两种方式原文地址: http://www.javaweb.cc/language/java/032291.shtml 第一种: ...

  5. JAVA中集合输出的四种方式

    在JAVA中Collection输出有四种方式,分别如下: 一) Iterator输出. 该方式适用于Collection的所有子类. public class Hello { public stat ...

  6. java中使用mongodb的几种方式

    最近有时间看了一下mongodb,因为mongodb更容易扩展所以考虑使用mongodb来保存数据. 首先下载安装mongodb,这是很简单的,装好后使用mongod命令就可以启动数据库.正式部署的话 ...

  7. java中设置代理的两种方式

    1 前言 有时候我们的程序中要提供可以使用代理访问网络,代理的方式包括http.https.ftp.socks代理.比如在IE浏览器设置代理. 那我们在我们的java程序中使用代理呢,有如下两种方式. ...

  8. java中实现同步的两种方式:syschronized和lock的区别和联系

    Lock是java.util.concurrent.locks包下的接口,Lock 实现提供了比使用synchronized 方法和语句可获得的更广泛的锁定操作,它能以更优雅的方式处理线程同步问题,我 ...

  9. java中遍历集合的三种方式

    第一种遍历集合的方式:将集合变为数组 package com.lw.List; import java.util.ArrayList; import java.util.List; import ja ...

随机推荐

  1. [TimLinux] Python 模块

    1. 概念 模块是最高级别的程序组织单元,它将程序文件和数据封装起来以便重用.实际上,模块往往对应Python文件,每一个文件都是一个模块,并且模块导入其他模块之后就可以使用导入模块定义的变量,模块和 ...

  2. Selenium 4 Python的最佳测试框架

    随着Python语言的使用越来越流行,基于Python的测试自动化框架也越来越流行.在项目选择最佳框架时,开发人员和测试人员会有些无法下手.做出选择是应该判断很多事情,框架的脚本质量,测试用例的简单性 ...

  3. LightOJ1355 Game Of CS(green 博弈)

    Jolly and Emily are two bees studying in Computer Science. Unlike other bees they are fond of playin ...

  4. python读取,显示,保存mnist图片

    python处理二进制 python的struct模块可以将整型(或者其它类型)转化为byte数组.看下面的代码. # coding: utf-8 from struct import * # 包装成 ...

  5. python + selenium WebDriver的环境配置

    想试用python语言来学习selenium WebDriver,首先需要搭建一个测试环境,从python安装到浏览器插件配置的详细步骤,总结如下: 一.python环境配置 1.从官网下载最新的一个 ...

  6. JS实现链式调用 a().b().c()

    function a() { this.b = function () { console.log('111') return this } this.c = function () { consol ...

  7. Java做成Zip文件,Java实现压缩文件

    import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import ...

  8. synchronized和volatile区别

    不同一: synchronized可以修饰方法, volatile只能修饰变量 不同二: synchronized是同步的 volatile修饰的变量具有可见性.

  9. node-sass下载失败

    在angular项目中下载依赖npm install时提示node-sass安装失败,解决方法如下: 1.下载win32-x64-57_binding.node文件至指定目录 2.添加环境变量: 变量 ...

  10. 在 ASP.NET Core 中使用 Serilog 进行日志记录

    目录 从 NuGet 安装 Serilog 在 Main函数 中配置 Serilog 在项目中使用 Serilog 进行日志输出 从 NuGet 安装 Serilog 核心的包是 Serilog 和 ...