下面展示了两种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()方法,既简单效率又高,还不
会出错的。