經過一組簡單的測試發現JAVA NIO提供的文件內存映射方法實現文件拷貝速度最快,不管是大文件還是小文件,特別是大文件的拷貝速度比普通方法提高20倍,唯一有個前提就是內存需要足夠大,否則文件映射肯定失敗(當然可以通過分割文件,部分映射的方法避免,但就比較麻煩了);其次NIO提供的文件管道傳輸速度也比較好,如果沒法做文件內存映射,推薦這種拷貝方法;另外,Buffer的大小,對於讀寫速度還是有影響的,基本就是Buffer越大讀寫越快(有個疑問就是Buffer.allocateDirec()效率提高不明顯);最後,總體看來NIO的效率比老IO高,不管使用哪種方式,老IO使用流讀寫只能一個字節一個字節的摳,NIO使用塊的方式讀寫還是相對比較快,所以沒有特別需求的情況下,推薦使用NIO,目前NIO基本能覆蓋老IO的所有功能(當然NIO還提供N多新功能)。
測試環境
123456789 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));
}
}
接下來請看第2頁精彩內容: http://www.linuxidc.com/Linux/2013-08/88903p2.htm