BufferedInputStream/BufferedOutputStream
内存的运算效率比硬盘快很多,所以只有降低硬盘的读取次数才会提高效率。
file_old -- BufferedInputStream(1024 * 8) -- BufferedOutputStream(buffer:1024 * 8) -- file_new
程序向流中写出字节时,不会直接写到文件中,会先写到缓冲区中,直到缓冲区写满,才会把缓冲区中的数据一次性写到文件中 flush。
1. FileOutputStream 普通
private static void customBufferStreamCopy(File source, File target) {
InputStream fis = null;
OutputStream fos = null;
try {
fis = new FileInputStream(source);
fos = new FileOutputStream(target);
byte[] buf = new byte[4096];
int i;
while ((i = fis.read(buf)) != -1) {
fos.write(buf, 0, i);
}
}
catch (Exception e) {
e.printStackTrace();
} finally {
close(fis);
close(fos);
}
public static void copyfile(File fromFile, File toFile,Boolean rewrite ){
if(!fromFile.exists()){
return;
}
if(!fromFile.isFile()){
return;
}
if(!fromFile.canRead()){
return;
}
if(!toFile.getParentFile().exists()){
toFile.getParentFile().mkdirs();
}
if(toFile.exists() && rewrite){
toFile.delete();
}
try {
FileInputStream fosfrom = new FileInputStream(fromFile);
FileOutputStream fosto = new FileOutputStream(toFile);
byte[] bt = new byte[1024];
int c;
while((c=fosfrom.read(bt)) > 0){
fosto.write(bt,0,c);
}
//关闭输入、输出流
fosfrom.close();
fosto.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static boolean copyFile(String srcFileName,String destFileName,boolean overlay){
File srcFile = new File(srcFileName); //根据一个路径得到File对象
//判断源文件是否存在
if(!srcFile.exists()){
try{
throw new Exception("源文件:"+srcFileName+"不存在!");
}catch(Exception e){
e.printStackTrace();//将异常内容存到日志文件中
}
return false;
}else if(!srcFile.isFile()){//判断是不是一个文件
try {
throw new Exception("复制文件失败,源文件:"+srcFileName+"不是一个文件!");
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
//判断目标文件是否存在
File destFile = new File(destFileName);//目标文件对象destFile
if(destFile.exists()){
//如果目标文件存在并允许覆盖
if(overlay){
//删除已经存在的目标文件
new File(destFileName).delete();
}
}else{
//如果目标文件所在目录不存在,则创建 目录
if(!destFile.getParentFile().exists()){
//目标文件所在目录不存在
//mkdirs():创建此抽象路径名指定的目录,包括所有必需但不存在的父目录
if(!destFile.getParentFile().mkdirs()){
//复制文件失败:创建目标文件所在目录失败
return false;
}
}
}
//复制文件
int byteread = 0;//读取的字节数
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(srcFile);
out = new FileOutputStream(destFile);
byte[] buffer = new byte[1024];
/*
* 方法说明:
* ①:将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
* write(byte[] b, int off, int len)
* b - 数据
* off - 数据中的起始偏移量。
* len - 要写入的字节数。
* ②:in.read(buffer))!=-1,是从流buffer中读取一个字节,当流结束的时候read返回-1
*/
while((byteread = in.read(buffer))!=-1){
out.write(buffer, 0, byteread);
}
return true;
} catch (FileNotFoundException e) {
return false;
} catch (IOException e) {
return false;
}finally{
try {
if(out!=null){
out.close();
}
if(in!=null){
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
2. BufferedOutputStream 快
private static void customBufferBufferedStreamCopy(File source, File target) {
InputStream fis = null;
OutputStream fos = null;
try {
fis = new BufferedInputStream(new FileInputStream(source));
fos = new BufferedOutputStream(new FileOutputStream(target));
byte[] buf = new byte[4096];
int i;
while ((i = fis.read(buf)) != -1) {
fos.write(buf, 0, i);
}
}
catch (Exception e) {
e.printStackTrace();
} finally {
close(fis);
close(fos);
}
}
FileChannel 方式(针对体积大的文件)而且FileChannel是多并发线程安全的。
1.private static void nioTransferCopy(File source, File target) {
FileChannel in = null;
FileChannel out = null;
FileInputStream inStream = null;
FileOutputStream outStream = null;
try {
inStream = new FileInputStream(source);
outStream = new FileOutputStream(target);
in = inStream.getChannel();
out = outStream.getChannel();
in.transferTo(0, in.size(), out); //连接两个通道,并且从in通道读取,然后写入out通道
} catch (IOException e) {
e.printStackTrace();
} finally {
close(inStream);
close(in);
close(outStream);
close(out);
}
}
2.private static void nioBufferCopy(File source, File target) {
FileChannel in = null;
FileChannel out = null;
FileInputStream inStream = null;
FileOutputStream outStream = null;
try {
inStream = new FileInputStream(source);
outStream = new FileOutputStream(target);
in = inStream.getChannel();
out = outStream.getChannel();
//类似使用了缓冲 ---- 么有直接连接通道写入的快
ByteBuffer buffer = ByteBuffer.allocate(4096);
while (in.read(buffer) != -1) {
buffer.flip();
out.write(buffer);
buffer.clear();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
close(inStream);
close(in);
close(outStream);
close(out);
}
}
3. / * 使用文件通道的方式复制文件
*/
public static void fileChannelCopy(String srcDirName,String destDirName){
FileInputStream fi = null;
FileOutputStream fo = null;
FileChannel in = null;
FileChannel out = null;
try {
fi = new FileInputStream(new File(srcDirName));
fo = new FileOutputStream( new File(destDirName));
in = fi.getChannel();//得到对应的文件通道
out = fo.getChannel();//得到对应的文件通道
/*
* public abstract long transferTo(long position, long count,
WritableByteChannel target)throws IOException;
* position - 文件中的位置,从此位置开始传输;必须为非负数
* count - 要传输的最大字节数;必须为非负数
* target - 目标通道
* 返回:
实际已传输的字节数,可能为零
*/
in.transferTo(0, in.size(), out);//连接两个通道,并且从in通道读取,然后写入out通道中
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
fi.close();
in.close();
fo.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileWriter 非常快 (FileWriter默认写page cache里,所以快)