众所周知,在Java中,实现文件复制的方式有很多,并且还要考虑到选用字符流还是字节流

如果仅仅只是文本文件的话,我们使用字符流无可厚非,但不一定所有的文件都是文本文件啊

在视频,音频方面,就要用到字节流的操作了

PS:在使用字符流的过程中,还要注意中文字符的编码问题

Java API中,我们也可以利用文件通道(FileChannel)来实现实现文件的复制,并且在文件越大的时候,用这个复制的效率越高

在这里,为了便于比较,我把三个方法写到了一起,并加入了耗时输出,我们可以通过耗时来比较那种方法最优

/**
 * 文件的复制操作——IO操作
 * @author Shawn·Zhang
 */

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.channels.FileChannel;

public class Example08 {

	public static void main(String[] args) throws Exception {
		//分别复制两个文件
		// E:\\java\\source.txt
		// F:\\革命歌曲\\004.mp3 国际歌(合唱版).mp3
		byteCopy(new File("E:\\java\\source.txt"), new File(
				"C:\\Users\\Z_DELL_PC\\Desktop\\target1.txt"));
		charCopy(new File("E:\\java\\source.txt"), new File(
				"C:\\Users\\Z_DELL_PC\\Desktop\\target2.txt"));
		fileChannelCopy(new File("E:\\java\\source.txt"), new File(
				"C:\\Users\\Z_DELL_PC\\Desktop\\target3.txt"));
	}

	/**
	 * 字节流复制方法
	 * @param source 源文件
	 * @param target 目标文件
	 */
	private static void byteCopy(File source, File target){
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		int len;//定义一个int类型的变量len,记住每次读取的一个字节
		try {
			bis = new BufferedInputStream(new FileInputStream(source));//创建一个带缓冲区的输入流
			bos = new BufferedOutputStream(new FileOutputStream(target));//创建一个带缓冲区的输出流
			long begintime = System.currentTimeMillis();//获取拷贝文件前的系统时间
			while((len=bis.read())!=-1){//读取一个字节并判断是否读到文件末尾
				bos.write(len);//将读到的字节写入文件
			}
			long endtime = System.currentTimeMillis();//获取拷贝文件后的系统时间
			System.out.println("字节流拷贝文件消耗的时间是:" + (endtime - begintime) + "毫秒");//输出耗时
		} catch (IOException e) {
			e.printStackTrace();
		} finally{
			try {
				bis.close();
				bos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	/**
	 * 字符流复制方法
	 * @param source 源文件
	 * @param target 目标文件
	 */
	private static void charCopy(File source, File target){
		BufferedReader br = null;
		BufferedWriter bw = null;
		String str;
		try {
			br = new BufferedReader(new FileReader(source));//创建一个bufferedreader缓冲对象
			bw = new BufferedWriter(new FileWriter(target));//创建一个bufferedwrite缓冲对象
			long begintime = System.currentTimeMillis();
			while((str=br.readLine())!=null){//每次读取一行文本,判断是否读到文本末尾
				bw.write(str);
				bw.newLine();//写入一个换行符,该方法会根据不同的操作系统生成相应的换行符
			}
			long endtime = System.currentTimeMillis();
			System.out.println("字符流拷贝文件消耗的时间是:"+(endtime-begintime)+"毫秒");//输出耗时
		} catch (IOException e) {
			e.printStackTrace();
		} finally{
			try {
				br.close();
				bw.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	/**
	 * 通过文件通道进行复制
	 * @param source 源文件
	 * @param target 目标文件
	 */
	private static void fileChannelCopy(File source, File target){
		FileInputStream s = null;
		FileOutputStream t = null;
		FileChannel in = null;
		FileChannel out = null;
		try {
			s = new FileInputStream(source);
			t = new FileOutputStream(target);
			in = s.getChannel();//得到对应的文件通道
			out = t.getChannel();//得到对应的文件通道
			long begintime = System.currentTimeMillis();
			in.transferTo(0, in.size(), out);//连接两个通道,并且从in通道读取,然后写入out通道
			long endtime = System.currentTimeMillis();
			System.out.println("API拷贝文件消耗的时间是:" + (endtime - begintime) + "毫秒");//输出耗时
		} catch (IOException e) {
			e.printStackTrace(); 
		} finally{
			try {
				s.close();
				t.close();
				in.close();
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

}

代码中,我分别拷贝了一个文本文件一个音频文件

java 复制文件夹中所有文件 java中文件的复制_文件复制

java 复制文件夹中所有文件 java中文件的复制_java_02

最终在耗时方面

文本文档:

java 复制文件夹中所有文件 java中文件的复制_字节流_03

音频文件:

java 复制文件夹中所有文件 java中文件的复制_java 复制文件夹中所有文件_04


从耗时可以看出,在复制小文件的时候,几种方式的速度相差无几,但随着文件的增大,Java提供的方法要略快一些,字节缓冲流次之。

PS:在测试中,我们使用字符流复制MP3文件,但在实际应用中,字符流在使用的过程中会造成音频格式损坏。切记~