比较IO流和NIO流做文件传输时的效果。
通过分别对500M\1G\1.5G文件拷贝比较不同方式传输的效率。
方法说明如下:
test 使用传统IO流FileInputStream对文件进行读写;
test1 使用NIO流的FileChannel(通道、缓冲池)和FileInputStream(文件流)对文件进行读写;
test2 使用NIO流的FileChannel(通道、缓冲池)和RandomAccessFile(随记文件类)对文件进行读写,写文件时缓冲池到通道;
test3 使用NIO流的FileChannel、MappedByteBuffer(通道、内存映射)和RandomAccessFile(随记文件类)对文件进行读写;
test4 使用NIO流的FileChannel(通道和通道连接方式)对文件进行读写;
test5 使用NIO流的FileChannel、ByteBuffer(通道、缓冲池)和RandomAccessFile(随记文件类)对文件进行读写,写文件时缓冲 池到缓冲池;
直接上代码:
package com.test;
import java.io.File;
import java.io.FileInputStream;
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;
/**
* 比较IO流和NIO流做文件传输时的效果
* @author Administrator
* @remark 通过分别对500M\1G\1.5G文件拷贝比较不同方式传输的效率
* 方法:
* test 使用传统IO流FileInputStream对文件进行读写
* test1 使用NIO流的FileChannel(通道、缓冲池)和FileInputStream(文件流)对文件进行读写
* test2 使用NIO流的FileChannel(通道、缓冲池)和RandomAccessFile(随记文件类)对文件进行读写,写文件时缓冲池到通道
* test3 使用NIO流的FileChannel、MappedByteBuffer(通道、内存映射)和RandomAccessFile(随记文件类)对文件进行读写
* test4 使用NIO流的FileChannel(通道和通道连接方式)对文件进行读写
* test5 使用NIO流的FileChannel、ByteBuffer(通道、缓冲池)和RandomAccessFile(随记文件类)对文件进行读写,写文件时缓冲池到缓冲池
*/
public class NioTest {
public static void main(String[] args) throws Exception {
NioTest nt = new NioTest();
long t=0;
for (int i = 1; i <= 5; i++) {
if(i==5)
System.out.print("Test:"+(t+=nt.test(i))/i+"ms ");
}
t=0;
for (int i = 1; i <= 5; i++) {
if(i==5)
System.out.print("Test1:"+(t+=nt.test1(i))/i+"ms ");
}
t=0;
for (int i = 1; i <= 5; i++) {
if(i==5)
System.out.print("Test2:"+(t+=nt.test2(i))/i+"ms ");
}
t=0;
for (int i = 1; i <= 5; i++) {
if(i==5)
System.out.print("Test3:"+(t+=nt.test3(i))/i+"ms ");
}
t=0;
for (int i = 1; i <= 5; i++) {
if(i==5)
System.out.print("Test4:"+(t+=nt.test4(i))/i+"ms ");
}
t=0;
for (int i = 1; i <= 5; i++) {
if(i==5)
System.out.println("Test5:"+(t+=nt.test5(i))/i+"ms");
}
}
/**
* 使用传统IO流FileInputStream对文件进行读写
* @param n
* @return
* @throws Exception
*/
public long test(int n) throws Exception {
byte[] bbb = new byte[4 * 1024];
File file=new File("C://Users//Administrator//Desktop//Test//t//0.mp4");
if(file.exists()) file.deleteOnExit();
FileInputStream fis = new FileInputStream(
"C://Users//Administrator//Desktop//Test//123.mp4");
FileOutputStream fos = new FileOutputStream(
"C://Users//Administrator//Desktop//Test//t//0.mp4");
long timeStar = System.currentTimeMillis();// 得到当前的时间
while (fis.read(bbb) != -1) {
fos.write(bbb);
}
long timeEnd = System.currentTimeMillis();// 得到当前的时间
long time=timeEnd - timeStar;
//System.out.println("Test方法第"+n+"次 cost time :" + time + "ms");
fos.flush();
fis.close();
fos.close();
return time;
}
/**
* 使用NIO流的FileChannel(通道、缓冲池)和FileInputStream(文件流)对文件进行读写
* @param n
* @return
* @throws Exception
*/
public long test1(int n) throws Exception {
long time=0;
File file=new File("C://Users//Administrator//Desktop//Test//t//1.mp4");
if(file.exists()) file.deleteOnExit();
ByteBuffer byteBuf = ByteBuffer.allocate(1024<<4);//16K
FileInputStream fis = new FileInputStream(
"C://Users//Administrator//Desktop//Test//123.mp4");
FileOutputStream fos = new FileOutputStream(
"C://Users//Administrator//Desktop//Test//t//1.mp4");
FileChannel ifc = fis.getChannel();
FileChannel ofc = fos.getChannel();
long timeStar = System.currentTimeMillis();// 得到当前的时间
while (ifc.read(byteBuf) != -1) {
byteBuf.flip();
while (byteBuf.hasRemaining()) {
ofc.write(byteBuf);
}
byteBuf.clear();
}
long timeEnd = System.currentTimeMillis();// 得到当前的时间
time=timeEnd - timeStar;
fos.flush();
ifc.close();
fis.close();
ofc.close();
fos.close();
return time;
}
/**
* 使用NIO流的FileChannel(通道、缓冲池)和RandomAccessFile(随记文件类)对文件进行读写
* @param n
* @return
* @throws Exception
*/
public long test2(int n) {
long time=0;
File file=new File("C://Users//Administrator//Desktop//Test//t//2.mp4");
if(file.exists()) file.deleteOnExit();
RandomAccessFile outRa =null;
RandomAccessFile inRa = null;
FileChannel outFc =null;
FileChannel inFc = null;
try {
long timeStar = System.currentTimeMillis();// 得到当前的时间
ByteBuffer byteBuf = ByteBuffer.allocate(1024<<4);//16K
outRa = new RandomAccessFile(
"C://Users//Administrator//Desktop//Test//t//2.mp4", "rw");
inRa = new RandomAccessFile(
"C://Users//Administrator//Desktop//Test//123.mp4", "rw");
outFc = outRa.getChannel();
inFc = inRa.getChannel();
// 根据 read返回实际读出的字节数 中止循环
while(inFc.read(byteBuf) != -1){
// 缓冲区翻转用于输出到foc
byteBuf.flip();
outFc.write(byteBuf);
// 清空缓冲区用于下次读取
byteBuf.clear();
}
long timeEnd = System.currentTimeMillis();
time=timeEnd - timeStar;
//System.out.println("Test2方法第"+n+"次 cost time :" + time + "ms");
} catch (Exception e) {
e.printStackTrace();
} finally {
// 安全释放资源
if(null!=inFc)
try {
inFc.close();
} catch (IOException e) {
e.printStackTrace();
}
if(null!=outFc)
try {
outFc.close();
} catch (IOException e) {
e.printStackTrace();
}
if(null!=inRa)
try {
inRa.close();
} catch (IOException e) {
e.printStackTrace();
}
if(null!=outRa)
try {
outRa.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return time;
}
/**
* 使用NIO流的FileChannel、MappedByteBuffer(通道、内存映射)和RandomAccessFile(随记文件类)对文件进行读写
* @param n
* @return
* @throws Exception
*/
public long test3(int n) throws Exception {
long time=0;
File file=new File("C://Users//Administrator//Desktop//Test//t//3.mp4");
if(file.exists()) file.deleteOnExit();
long length = 0x8000000; // 128 Mb
RandomAccessFile outRa =null;
RandomAccessFile inRa = null;
FileChannel outFc =null;
FileChannel inFc = null;
try {
long timeStar = System.currentTimeMillis();// 得到当前的时间
outRa = new RandomAccessFile(
"C://Users//Administrator//Desktop//Test//t//3.mp4","rw");
inRa = new RandomAccessFile(
"C://Users//Administrator//Desktop//Test//123.mp4","rw");
outFc = outRa.getChannel();
inFc = inRa.getChannel();
MappedByteBuffer mbb = null;
long num = inFc.size()%length==0?inFc.size()/length:inFc.size()/length+1;
for (long i = 0; i < num; i++) {
mbb = inFc.map(FileChannel.MapMode.READ_WRITE, i*length,length);
outFc.write(mbb);
outFc.force(true);
mbb.clear();
}
long timeEnd = System.currentTimeMillis();
time=timeEnd - timeStar;
//System.out.println("Test3方法第"+n+"次 cost time :" + time + "ms");
} catch (Exception e) {
e.printStackTrace();
} finally {
// 安全释放资源
if(null!=inFc)
try {
inFc.close();
} catch (IOException e) {
e.printStackTrace();
}
if(null!=outFc)
try {
outFc.close();
} catch (IOException e) {
e.printStackTrace();
}
if(null!=inRa)
try {
inRa.close();
} catch (IOException e) {
e.printStackTrace();
}
if(null!=outRa)
try {
outRa.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return time;
}
/**
* 使用NIO流的FileChannel(通道和通道连接方式)对文件进行读写
* @param n
* @return
* @throws Exception
*/
public long test4(int n) throws Exception {
long time=0;
File file=new File("C://Users//Administrator//Desktop//Test//t//4.mp4");
if(file.exists()) file.deleteOnExit();
RandomAccessFile outRa =null;
RandomAccessFile inRa = null;
FileChannel outFc =null;
FileChannel inFc = null;
try {
long timeStar = System.currentTimeMillis();// 得到当前的时间
outRa = new RandomAccessFile(
"C://Users//Administrator//Desktop//Test//t//4.mp4","rw");
inRa = new RandomAccessFile(
"C://Users//Administrator//Desktop//Test//123.mp4","rw");
outFc = outRa.getChannel();
inFc = inRa.getChannel();
outFc.transferFrom(inFc, 0, inFc.size());
long timeEnd = System.currentTimeMillis();
time=timeEnd - timeStar;
//System.out.println("Test4方法第"+n+"次 cost time :" + time + "ms");
} catch (Exception e) {
e.printStackTrace();
} finally {
// 安全释放资源
if(null!=inFc)
try {
inFc.close();
} catch (IOException e) {
e.printStackTrace();
}
if(null!=outFc)
try {
outFc.close();
} catch (IOException e) {
e.printStackTrace();
}
if(null!=inRa)
try {
inRa.close();
} catch (IOException e) {
e.printStackTrace();
}
if(null!=outRa)
try {
outRa.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return time;
}
/**
* 使用NIO流的FileChannel、ByteBuffer(通道、缓冲池)和RandomAccessFile(随记文件类)对文件进行读写
* @param n
* @return
* @throws Exception
*/
public long test5(int n) throws Exception {
long time=0;
File file=new File("C://Users//Administrator//Desktop//Test//t//5.mp4");
if(file.exists()) file.deleteOnExit();
RandomAccessFile outRa =null;
RandomAccessFile inRa = null;
FileChannel outFc =null;
FileChannel inFc = null;
try {
long timeStar = System.currentTimeMillis();// 得到当前的时间
outRa = new RandomAccessFile(
"C://Users//Administrator//Desktop//Test//t//5.mp4","rw");
inRa = new RandomAccessFile(
"C://Users//Administrator//Desktop//Test//123.mp4","rw");
outFc = outRa.getChannel();
inFc = inRa.getChannel();
ByteBuffer bb,cc = null;
long i = 0;
long size = inFc.size()/50;
while(i<inFc.size()&&(inFc.size()-i)>size){
bb = inFc.map(FileChannel.MapMode.READ_WRITE, i,size);
cc = outFc.map(FileChannel.MapMode.READ_WRITE, i,size);
cc.put(bb);
i+=size;
bb.clear();
cc.clear();
}
long timeEnd = System.currentTimeMillis();
time=timeEnd - timeStar;
//System.out.println("Test5方法第"+n+"次 cost time :" + time + "ms");
} catch (Exception e) {
e.printStackTrace();
} finally {
// 安全释放资源
if(null!=inFc)
try {
inFc.close();
} catch (IOException e) {
e.printStackTrace();
}
if(null!=outFc)
try {
outFc.close();
} catch (IOException e) {
e.printStackTrace();
}
if(null!=inRa)
try {
inRa.close();
} catch (IOException e) {
e.printStackTrace();
}
if(null!=outRa)
try {
outRa.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return time;
}
}
以下是运行传输结束比较:
*************************************500M文件************************************
Test:618ms Test1:225ms Test2:1368ms Test3:3566ms Test4:160ms Test5:330ms
Test:561ms Test1:382ms Test2:1329ms Test3:3368ms Test4:142ms Test5:312ms
Test:626ms Test1:236ms Test2:1436ms Test3:3448ms Test4:163ms Test5:305ms
Test:736ms Test1:268ms Test2:1561ms Test3:6435ms Test4:161ms Test5:243ms
*************************************1.13G文件************************************
Test:8439ms Test1:3665ms Test2:8330ms Test3:7419ms Test4:2381ms Test5:3557ms
Test:4188ms Test1:5398ms Test2:14902ms Test3:5907ms Test4:2007ms Test5:9520ms
Test:2985ms Test1:8266ms Test2:4998ms Test3:7892ms Test4:2270ms Test5:10894ms
Test:7416ms Test1:6306ms Test2:5537ms Test3:6759ms Test4:1930ms Test5:10058ms
*************************************1.5G文件************************************
Test:7920ms Test1:3733ms Test2:5194ms Test3:6278ms Test4:1812ms Test5:797ms
Test:6178ms Test1:5482ms Test2:9191ms Test3:5667ms Test4:1930ms Test5:32867ms
Test:2774ms Test1:4606ms Test2:4973ms Test3:6189ms Test4:1856ms Test5:750ms
Test:7268ms Test1:3052ms Test2:4863ms Test3:11470ms Test4:1681ms Test5:35025ms
最终测试证明,使用NIO流的传输文件效率较高,尤其使用第四种方式(通道到通道的传输)效果更明显。