生动讲解使用不同方式操作File文件的方法之间的差异

下面展示了两种java文件操作的方式,

第一种是通过流来实现对文件的复制
第二种是通过reader的方式来实现的
第三种是通过buffer来实现的
而且每一个方法之后都附有了对应的方法的使用btye[]/char[]的方法,读者可以自行的测试它们的运行时间来比较它们的性能的优劣

 
package com.dada.handlefile;

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.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Date;

public class CopyFile {
	public static void main(String[] args) throws Exception {
		CopyFile cf = new CopyFile();
		File source = new File("source.JPG");
		File dest = new File("dest.JPG");
		File dest1 = new File("dest1.JPG");
		
//		cf.check(source);
//		// 测试第一种方法执行的时间
//		File dest1 = new File("temp1.jpg");
//		cf.check(dest1);
//		Date m1Begin = new Date();
//		cf.createFileByStream(source, dest1);
//		Date m1End = new Date();
//		long t1 = (m1End.getTime() - m1Begin.getTime());
//
//		// 测试第二种方法执行的时间
//		File dest2 = new File("temp2.jpg");
//		cf.check(dest2);
//		Date m2Begin = new Date();
//		cf.createFileByReader(source, dest2);
//		Date m2End = new Date();
//		long t2 = (m2End.getTime() - m2Begin.getTime());
//
//		// 第三种方法执行的时间
//		File dest3 = new File("temp3.jpg");
//		cf.check(dest3);
//		Date m3Begin = new Date();
//		cf.createFileByBuffer(source, dest3);
//		Date m3End = new Date();
//		long t3 = (m3End.getTime() - m3Begin.getTime());
//
//		// 第一和第二种方法之间时间只差
//		long difM1ToM2 = t1 - t2;
//		// 倍数
//		double multipleM1ToM2 = t1 / t2 * 1.0;
//
//		long difM2ToM3 = t2 - t3;
//		double multipleM2ToM3 = t2 / t3 * 1.0;
//
//		long difM1ToM3 = t1 - t3;
//		double multipleM1ToM3 = t1 / t3 * 1.0;
//
//		System.out.println("第一个方法执行时间: " + t1 + "\t第一和第二个方法执行的时间差: "
//				+ difM1ToM2 + "\t倍数差: " + multipleM1ToM2);
//		System.out.println("第二个方法执行时间: " + t2 + "\t第二和第三个方法执行的时间差: "
//				+ difM2ToM3 + "\t倍数差: " + multipleM2ToM3);
//		System.out.println("第三个方法执行时间: " + t3 + "\t第一和第三个方法执行的时间差: "
//				+ difM1ToM3 + "\t倍数差: " + multipleM1ToM3);
		
	}

	/**
	 * 检测指定文件是否存在,不存在就创建
	 * 
	 * @param f
	 */
	public void check(File f) {
		if (!f.exists()) {
			try {
				f.createNewFile();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	/**
	 * 通过stream来复制文件
	 * @param source
	 * @param dest
	 * @throws Exception
	 */
	public void createFileByStream(File source, File dest) throws Exception {
		FileInputStream in = new FileInputStream(source);
		FileOutputStream out = new FileOutputStream(dest);
		int read = in.read();
		while (read != -1) {
			out.write(read);
			read = in.read();
		}
		out.close();
		in.close();
	}

	public void createFileByStreamWithByte(File source, File dest) throws Exception {
		FileInputStream in = new FileInputStream(source);
		FileOutputStream out = new FileOutputStream(dest);
		byte[] buf = new byte[1024];
		while (in.read(buf) != -1) {
			out.write(buf);
		}
		out.close();
		in.close();
	}

	/**
	 * 使用reader来复制文件
	 * @param source
	 * @param dest
	 * @throws Exception
	 */
	public void createFileByReader(File source, File dest) throws Exception {
		FileReader fr = new FileReader(source);
		FileWriter fw = new FileWriter(dest);
		int read = fr.read();
		while (read != -1) {
			fw.write(read);
			read = fr.read();
		}
		fw.close();
		fr.close();
	}
	
	public void createFileByReaderWithChar(File source, File dest) throws Exception {
		FileReader fr = new FileReader(source);
		FileWriter fw = new FileWriter(dest);
		char[] buf = new char[2048];
		while (fr.read(buf) != -1) {
			fw.write(buf);
		}
		fw.close();
		fr.close();
	}

	/**
	 * 通过buffer来复制文件
	 * @param source
	 * @param dest
	 * @throws Exception
	 */
	public void createFileByBuffer(File source, File dest) throws Exception {
		// 封装stream
		FileInputStream in = new FileInputStream(source);
		// 把stream封装成为reader
		InputStreamReader isr = new InputStreamReader(in);
		// 把reader封装成为buffer
		BufferedReader br = new BufferedReader(isr);
		FileOutputStream out = new FileOutputStream(dest);
		OutputStreamWriter osw = new OutputStreamWriter(out);
		BufferedWriter bw = new BufferedWriter(osw);
		int read = br.read();
		while (read != -1) {
			bw.write(read);
			read = br.read();
		}
		bw.close();
		osw.close();
		out.close();
		br.close();
		isr.close();
		in.close();
	}
	
	public void createFileByBufferWithChar(File source, File dest) throws Exception {
		// 封装stream
		FileInputStream in = new FileInputStream(source);
		// 把stream封装成为reader
		InputStreamReader isr = new InputStreamReader(in);
		// 把reader封装成为buffer
		BufferedReader br = new BufferedReader(isr);
		FileOutputStream out = new FileOutputStream(dest);
		OutputStreamWriter osw = new OutputStreamWriter(out);
		BufferedWriter bw = new BufferedWriter(osw);
		char[] buf = new char[2048];
		while (br.read(buf) != -1) {
			bw.write(buf);
		}
		bw.close();
		osw.close();
		out.close();
		br.close();
		isr.close();
		in.close();
	}
}
运行结果:

 

第一个方法执行时间: 7019  第一和第二个方法执行的时间差: 6894   倍数差: 56.0
第二个方法执行时间: 125    第二和第三个方法执行的时间差: 79        倍数差: 2.0
第三个方法执行时间: 46      第一和第三个方法执行的时间差: 6973    倍数差: 152.0

 

可见差异是非常之大的,相差超过150倍这个,

为什么呢?我觉得就好像是这样的:

我们可以打个比喻:

我们把文件的复制可以看成是在两个地方之间搬运东西,

有三种运输工具:

摩托车(对应inputStream/outputStream),

三马车(对应InputStreamReader/outtStreamReader),

大卡车(对应BufferedReader/BufferedWriter),

它们之间的关系式摩托车可以单独的运送,送到指定地点之后

回来再次重复原来的动作,也可以把它上面的传送带(inputStream

可以封装进入inputStreamReader里面),同理三马车也可以单独

的运送,也可以把它的传送带(inputStreamReader可以封装进入

BufferedReader里面)连接到卡车上,但是因为卡车太高了,所以土

无法直接的装进卡车,所以如果要使用卡车运送土的话,就需要摩托

车和三马车提供传送带,把土送进卡车里(对应stream的两个封装

过程)。

这是读取过程,写入的过程也是一样的。需要把土从卡车上面通过

传送带一级一级的传输到地面。

 

那么直接使用摩托车,三马车和三个一起使用的效率差在哪里了?

其实这中间取数据和读数据的速度应该是没有太大差异的,差异就在

于它们取的频率差异很大,第一种方法是stream是字节它们的容量很

小,所以它们每一次只能够传输几个字节,而以此类推越往上一次传输

的容量越大,这样的话,往返的次数就少了,花费在"路"上面的时间就少

了,同样是运送100立方米的土,卡车要一次一个小时就够了,而三马车

要10次每一次要3个小时,而摩托车要100次每一次6个小时,这时间差

异就很明显了.

 

另外在读写文件的时候最好使用各个对象的read()方法,因为这个方法

是以字节的方式读取的,不论是什么格式的文件都不会出错,但是如果

你使用buffer的readLine()方法,或者是它的read(byte[] b);方法,结果都

可能会出现问题,比如用readLine()方法读取文本文件,在你再次的写出

去的时候,它里面的所有的换行都会被去掉的.

如果是用它来读取其他格式文件,比如jpg文件结果基本上都是错误的,

所以说在复制的时候直接就调用它的read()方法,既简单效率又高,还不

会出错的。


 

 


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值