您的位置:首页 > 编程语言 > Java开发

Java实现文件拷贝 推荐

2013-08-14 16:58 330 查看
经过一组简单的测试发现JAVA NIO提供的文件内存映射方法实现文件拷贝速度最快,不管是大文件还是小文件,特别是大文件的拷贝速度比普通方法提高20倍,唯一有个前提就是内存需要足够大,否则文件映射肯定失败(当然可以通过分割文件,部分映射的方法避免,但就比较麻烦了);其次NIO提供的文件管道传输速度也比较好,如果没法做文件内存映射,推荐这种拷贝方法;另外,Buffer的大小,对于读写速度还是有影响的,基本就是Buffer越大读写越快(有个疑问就是Buffer.allocateDirec()效率提高不明显);最后,总体看来NIO的效率比老IO高,不管使用哪种方式,老IO使用流读写只能一个字节一个字节的抠,NIO使用块的方式读写还是相对比较快,所以没有特别需求的情况下,推荐使用NIO,目前NIO基本能覆盖老IO的所有功能(当然NIO还提供N多新功能)。

测试环境

Eclipse(Juno) JVM(Sun JDK1.7) 参数:
-Xms1536m
-Xmx1536m
-Xverify:none -XX:+UseParallelGC
-XX:PermSize=128M
-XX:MaxPermSize=128M
OS参数:
Win7 64Bit + 4GB
物理磁盘空间充足


测试代码

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
public class FileCopy {
private static final int BUFFER_SIZE_1024 = 1024;
private static final int BUFFER_SIZE_4096 = 4096;
private static final int BUFFER_SIZE_10240 = 10240;

private static final String FROM_FILE_42MB = "G:/from_42MB.rar";
private static final String FROM_FILE_1GB = "G:/from_350MB.rar";

private static int BUFFER_SIZE = BUFFER_SIZE_1024;
private static String FROM_FILE = FROM_FILE_42MB;
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
System.out.println("File :" + FROM_FILE + " ---- Buffer Size : " + BUFFER_SIZE + "--------------");
testFileCopy();

BUFFER_SIZE = BUFFER_SIZE_4096;
System.out.println("File :" + FROM_FILE + " ---- Buffer Size : " + BUFFER_SIZE + "--------------");
testFileCopy();

BUFFER_SIZE = BUFFER_SIZE_10240;
System.out.println("File :" + FROM_FILE + " ---- Buffer Size : " + BUFFER_SIZE + "--------------");
testFileCopy();

BUFFER_SIZE = BUFFER_SIZE_1024;
FROM_FILE = FROM_FILE_1GB;
System.out.println("File :" + FROM_FILE + " ---- Buffer Size : " + BUFFER_SIZE + "--------------");
testFileCopy();

BUFFER_SIZE = BUFFER_SIZE_4096;
FROM_FILE = FROM_FILE_1GB;
System.out.println("File :" + FROM_FILE + " ---- Buffer Size : " + BUFFER_SIZE + "--------------");
testFileCopy();

BUFFER_SIZE = BUFFER_SIZE_10240;
FROM_FILE = FROM_FILE_1GB;
System.out.println("File :" + FROM_FILE + " ---- Buffer Size : " + BUFFER_SIZE + "--------------");
testFileCopy();

}
private static void testFileCopy() throws FileNotFoundException,
IOException {
coypByMbb();
copyByNioTransferFrom();
copyByNioTransferTo();
coypByBufferRead();
coypByFastBufferRead();
coypByStream();//Old IO style
}
/**
* 使用FileChannel.transferFrom()实现
* @throws FileNotFoundException
* @throws IOException
*/
private static void copyByNioTransferFrom() throws FileNotFoundException,
IOException {
long startTime = System.currentTimeMillis();
RandomAccessFile fromFile = new RandomAccessFile(FROM_FILE, "rw");
FileChannel fromChannel = fromFile.getChannel();
RandomAccessFile toFile = new RandomAccessFile("G:/to1.rar", "rw");
FileChannel toChannel = toFile.getChannel();
long position = 0;
long count = fromChannel.size();
toChannel.transferFrom(fromChannel, position, count);
long endTime = System.currentTimeMillis();
System.out.println("copyByNioTransferFrom time consumed(buffer size no effect) : "
+ (endTime - startTime));
}
/**
* 使用FileChannel.transferTo()实现
* @throws FileNotFoundException
* @throws IOException
*/
private static void copyByNioTransferTo() throws FileNotFoundException,
IOException {
long startTime = System.currentTimeMillis();
RandomAccessFile fromFile = new RandomAccessFile(FROM_FILE, "rw");
FileChannel fromChannel = fromFile.getChannel();
RandomAccessFile toFile = new RandomAccessFile("G:/to2.rar", "rw");
FileChannel toChannel = toFile.getChannel();
long position = 0;
long count = fromChannel.size();
fromChannel.transferTo(position, count, toChannel);
long endTime = System.currentTimeMillis();
System.out.println("copyByNioTransferTo time consumed(buffer size no effect) : "
+ (endTime - startTime));
}
/**
* 使用Channel, Buffer简单读写实现
* @throws IOException
*/
private static void coypByBufferRead() throws IOException {
long startTime = System.currentTimeMillis();
FileInputStream fin = new FileInputStream(FROM_FILE);
FileOutputStream fout = new FileOutputStream("G:/to3.rar");
FileChannel fcin = fin.getChannel();
FileChannel fcout = fout.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
while (true) {
buffer.clear();
int r = fcin.read(buffer);
if (r == -1) {
break;
}
buffer.flip();
fcout.write(buffer);
}
long endTime = System.currentTimeMillis();
System.out.println("coypByBufferRead time consumed(buffer size take effect) : "
+ (endTime - startTime));
}
/**
* 使用连续内存的Buffer实现
* @throws IOException
*/
private static void coypByFastBufferRead() throws IOException {
long startTime = System.currentTimeMillis();
FileInputStream fin = new FileInputStream(FROM_FILE);
FileOutputStream fout = new FileOutputStream("G:/to4.rar");
FileChannel fcin = fin.getChannel();
FileChannel fcout = fout.getChannel();
ByteBuffer buffer = ByteBuffer.allocateDirect(BUFFER_SIZE);
while (true) {
buffer.clear();
int r = fcin.read(buffer);
if (r == -1) {
break;
}
buffer.flip();
fcout.write(buffer);
}
long endTime = System.currentTimeMillis();
System.out.println("coypByFastBufferRead time consumed(buffer size take effect) : "
+ (endTime - startTime));
}
/**
* 使用文件内存映射实现
* @throws IOException
*/
private static void coypByMbb() throws IOException {
long startTime = System.currentTimeMillis();
FileInputStream fin = new FileInputStream(FROM_FILE);
RandomAccessFile fout = new RandomAccessFile("G:/to5.rar", "rw");
FileChannel fcin = fin.getChannel();
FileChannel fcout = fout.getChannel();
MappedByteBuffer mbbi = fcin.map(FileChannel.MapMode.READ_ONLY, 0,
fcin.size());
MappedByteBuffer mbbo = fcout.map(FileChannel.MapMode.READ_WRITE, 0,
fcin.size());
mbbo.put(mbbi);
mbbi.clear();
mbbo.clear();
long endTime = System.currentTimeMillis();
System.out
.println("coypByMbb time consumed(buffer size no effect) : " + (endTime - startTime));
}
/**
* 使用传统IO的流读写方式实现
* @throws IOException
*/
private static void coypByStream() throws IOException {
long startTime = System.currentTimeMillis();
FileInputStream fin = new FileInputStream(FROM_FILE);
FileOutputStream fout = new FileOutputStream("G:/to6.rar");
byte[] buffer = new byte[BUFFER_SIZE];
while (true) {
int ins = fin.read(buffer);
if (ins == -1) {
fin.close();
fout.flush();
fout.close();
break;
} else{
fout.write(buffer, 0, ins);
}
}
long endTime = System.currentTimeMillis();
System.out.println("coypByStream time consumed(buffer size take effect) : " + (endTime - startTime));
}
}
测试结果
File :G:/from_42MB.rar ---- Buffer Size : 1024--------------
coypByMbb time consumed(buffer size no effect) : 47
copyByNioTransferFrom time consumed(buffer size no effect) : 62
copyByNioTransferTo time consumed(buffer size no effect) : 47
coypByBufferRead time consumed(buffer size take effect) : 249
coypByFastBufferRead time consumed(buffer size take effect) : 188
coypByStream time consumed(buffer size take effect) : 187

File :G:/from_42MB.rar ---- Buffer Size : 4096--------------
coypByMbb time consumed(buffer size no effect) : 15
copyByNioTransferFrom time consumed(buffer size no effect) : 16
copyByNioTransferTo time consumed(buffer size no effect) : 31
coypByBufferRead time consumed(buffer size take effect) : 125
coypByFastBufferRead time consumed(buffer size take effect) : 79
coypByStream time consumed(buffer size take effect) : 93

File :G:/from_42MB.rar ---- Buffer Size : 10240--------------
coypByMbb time consumed(buffer size no effect) : 16
copyByNioTransferFrom time consumed(buffer size no effect) : 32
copyByNioTransferTo time consumed(buffer size no effect) : 31
coypByBufferRead time consumed(buffer size take effect) : 78
coypByFastBufferRead time consumed(buffer size take effect) : 62
coypByStream time consumed(buffer size take effect) : 63

File :G:/from_350MB.rar ---- Buffer Size : 1024--------------
coypByMbb time consumed(buffer size no effect) : 280
copyByNioTransferFrom time consumed(buffer size no effect) : 453
copyByNioTransferTo time consumed(buffer size no effect) : 7785
coypByBufferRead time consumed(buffer size take effect) : 8144
coypByFastBufferRead time consumed(buffer size take effect) : 7068
coypByStream time consumed(buffer size take effect) : 8503

File :G:/from_350MB.rar ---- Buffer Size : 4096--------------
coypByMbb time consumed(buffer size no effect) : 1904
copyByNioTransferFrom time consumed(buffer size no effect) : 5978
copyByNioTransferTo time consumed(buffer size no effect) : 7379
coypByBufferRead time consumed(buffer size take effect) : 7621
coypByFastBufferRead time consumed(buffer size take effect) : 7474
coypByStream time consumed(buffer size take effect) : 8200

File :G:/from_350MB.rar ---- Buffer Size : 10240--------------
coypByMbb time consumed(buffer size no effect) : 328
copyByNioTransferFrom time consumed(buffer size no effect) : 6864
copyByNioTransferTo time consumed(buffer size no effect) : 7021
coypByBufferRead time consumed(buffer size take effect) : 7199
coypByFastBufferRead time consumed(buffer size take effect) : 7941
coypByStream time consumed(buffer size take effect) : 7801
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  JAVA 文件拷贝 NIO