作者:tacy.lee
写了一个解压缩zip包的方法来测试,测试代码如下:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
/**
* @author tacy.lee@gmail.com
*
*/
public class TestNIO {
public static void extract(File zipFile,File destDir) throws Exception{
ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile));
ZipEntry zie;
while((zie = zis.getNextEntry()) != null){
String entryName = zie.getName();
File newFile = new File(destDir,entryName);
int count;
byte[] data = new byte[8192];
if(zie.isDirectory()){
newFile.mkdirs();
}else{
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(newFile));
while((count = zis.read(data)) != -1){
bos.write(data,0,count);
}
bos.flush();
bos.close();
}
}
zis.close();
}
public static void extractBuf(File zipFile, File destDir) throws Exception {
BufferedInputStream bi = new BufferedInputStream(new FileInputStream(zipFile));
ZipInputStream zis = new ZipInputStream(bi);
ZipEntry zie;
int BUFFER_SIZE = 8192;
while ((zie = zis.getNextEntry()) != null) {
String entryName = zie.getName();
// System.out.println("Extracting: " + zipentry.getName());
File newFile = new File(destDir , entryName);
byte[] data = new byte[BUFFER_SIZE];
int count;
if (zie.isDirectory()) {
newFile.mkdirs();
} else {
FileOutputStream fos = new FileOutputStream(newFile);
BufferedOutputStream bos = new BufferedOutputStream(fos,BUFFER_SIZE);
while((count = zis.read(data,0,BUFFER_SIZE)) != -1){
bos.write(data,0,count);
}
bos.flush();
bos.close();
}
}
zis.close();
}
public static void extractNIOzf(File zipFile,File destDir) throws Exception{
ZipFile zf = new ZipFile(zipFile);
ZipEntry zie = null;
Enumeration et = zf.entries();
while(et.hasMoreElements()){
zie = (ZipEntry)et.nextElement();
File newFile = new File(destDir,zie.getName());
ReadableByteChannel rc = Channels.newChannel(zf.getInputStream(zie));
if(zie.isDirectory()){
newFile.mkdirs();
}else{
FileOutputStream fos = new FileOutputStream(newFile);
FileChannel fc = fos.getChannel();
fc.transferFrom(rc, 0, zie.getSize());
fos.close();
}
}
zf.close();
}
public static void extractNIO(File zipFile,File destDir)throws Exception{
BufferedInputStream bi = new BufferedInputStream(new FileInputStream(zipFile));
ZipInputStream zin = new ZipInputStream(bi);
ZipEntry zie;
ReadableByteChannel rc = Channels.newChannel(zin);
while((zie = zin.getNextEntry()) != null){
String entryName = zie.getName();
File newFile = new File(destDir,entryName);
if(zie.isDirectory()){
newFile.mkdirs();
}else{
FileOutputStream fos = new FileOutputStream(newFile);
FileChannel fc = fos.getChannel();
long count = 0;
long size = zie.getSize();
// while(count<size){
// long written = fc.transferFrom(rc, count, size);
// count += written;
// }
fc.transferFrom(rc,0,zie.getSize());
fos.close();
}
}
zin.close();
}
public static void main(String[] args){
if (args.length !=3){
System.out.println("Usage: TestNIO mode zipFile destDir");
System.out.println("mode:");
System.out.println(" extract");
System.out.println(" extractBuf");
System.out.println(" extractNIO");
System.out.println(" extractNIOzf");
System.exit(1);
}
File fs = new File(args[1]);
File dest = new File(args[2]);
try {
long avg = 0;
for(int i=0;i<10;i++){
long st = System.nanoTime();
if("extract".equals(args[0].toLowerCase()))
extract(fs,dest);
if("extractbuf".equals(args[0].toLowerCase()))
extractBuf(fs,dest);
if("extractnio".equals(args[0].toLowerCase()))
extractNIO(fs, dest);
if("extractniozf".equals(args[0].toLowerCase()))
extractNIOzf(fs,dest);
long time = System.nanoTime()-st;
System.out.println(time);
avg += time;
}
System.out.println("avg time:" + avg/10);
} catch (Exception e) {
e.printStackTrace();
}
}
}
测试结果:
d:\temp>java TestNIO extract d:\temp\eoshome.zip d:\temp\temp
5078282016
12635255040
10226276244
13185518830
11942373961
17426315635
15663583500
12787992329
12557049290
11303703403
avg time:12280635024
d:\temp>java TestNIO extractbuf d:\temp\eoshome.zip d:\temp\temp
7431395610
9422945654
9896290730
8881473484
8312653703
11012962262
13153371168
11235213134
8617239621
11440966101
avg time:9940451146
d:\temp>java TestNIO extractNIO d:\temp\eoshome.zip d:\temp\temp
4530841769
9990226132
12335196233
10000922464
10526305997
8983492315
9554596184
8798381359
9946382291
10512609564
avg time:9517895430
来看看他们都怎么执行IO操作的
1、extract
29082 13:54:44.3778096 java.exe 4004 ReadFile D:\temp\eoshome.zip SUCCESS Offset: 2,462,554, Length: 512
29083 13:54:44.3778431 java.exe 4004 ReadFile D:\temp\eoshome.zip SUCCESS Offset: 2,463,066, Length: 512
29084 13:54:44.3778741 java.exe 4004 ReadFile D:\temp\eoshome.zip SUCCESS Offset: 2,463,578, Length: 512
29085 13:54:44.3779071 java.exe 4004 ReadFile D:\temp\eoshome.zip SUCCESS Offset: 2,464,090, Length: 512
29086 13:54:44.3779373 java.exe 4004 ReadFile D:\temp\eoshome.zip SUCCESS Offset: 2,464,602, Length: 512
29087 13:54:44.3779674 java.exe 4004 ReadFile D:\temp\eoshome.zip SUCCESS Offset: 2,465,114, Length: 512
29088 13:54:44.3780018 java.exe 4004 ReadFile D:\temp\eoshome.zip SUCCESS Offset: 2,465,626, Length: 512
29089 13:54:44.3780356 java.exe 4004 ReadFile D:\temp\eoshome.zip SUCCESS Offset: 2,466,138, Length: 512
29091 13:54:44.3780660 java.exe 4004 ReadFile D:\temp\eoshome.zip SUCCESS Offset: 2,466,650, Length: 512
29092 13:54:44.3781029 java.exe 4004 ReadFile D:\temp\eoshome.zip SUCCESS Offset: 2,467,162, Length: 512
29093 13:54:44.3781496 java.exe 4004 ReadFile D:\temp\eoshome.zip SUCCESS Offset: 2,467,674, Length: 512
29094 13:54:44.3781800 java.exe 4004 ReadFile D:\temp\eoshome.zip SUCCESS Offset: 2,468,186, Length: 512
29095 13:54:44.3782124 java.exe 4004 ReadFile D:\temp\eoshome.zip SUCCESS Offset: 2,468,698, Length: 512
29096 13:54:44.3782407 java.exe 4004 ReadFile D:\temp\eoshome.zip SUCCESS Offset: 2,469,210, Length: 512
29097 13:54:44.3782694 java.exe 4004 ReadFile D:\temp\eoshome.zip SUCCESS Offset: 2,469,722, Length: 512
29098 13:54:44.3783060 java.exe 4004 WriteFile D:\temp\temp\base\lib\3rd\ant.jar FAST IO DISALLOWED Offset: 1,177,698, Length: 7,753
29099 13:54:44.3783166 java.exe 4004 WriteFile D:\temp\temp\base\lib\3rd\ant.jar SUCCESS Offset: 1,177,698, Length: 7,753
ZipInputStream每次读取文件长度512字节,每次写入文件长度不定,文件读取操作非常频繁。
2、extractBuf
22350 14:03:05.1736921 java.exe 1128 QueryStandardInformationFile D:\temp\eoshome.zip SUCCESS AllocationSize: 38,592,512, EndOfFile: 38,592,090, NumberOfLinks: 1, DeletePending: False, Directory: False
22351 14:03:05.1737072 java.exe 1128 ReadFile D:\temp\eoshome.zip SUCCESS Offset: 1,359,872, Length: 8,192
22352 14:03:05.1737740 java.exe 1128 WriteFile D:\temp\temp\base\lib\3rd\ant.jar SUCCESS Offset: 31,236, Length: 7,914
22353 14:03:05.1740799 java.exe 1128 QueryStandardInformationFile D:\temp\eoshome.zip SUCCESS AllocationSize: 38,592,512, EndOfFile: 38,592,090, NumberOfLinks: 1, DeletePending: False, Directory: False
22354 14:03:05.1740938 java.exe 1128 ReadFile D:\temp\eoshome.zip SUCCESS Offset: 1,368,064, Length: 8,192
22355 14:03:05.1741394 java.exe 1128 WriteFile D:\temp\temp\base\lib\3rd\ant.jar SUCCESS Offset: 39,150, Length: 7,719
22358 14:03:05.1744629 java.exe 1128 WriteFile D:\temp\temp\base\lib\3rd\ant.jar SUCCESS Offset: 46,869, Length: 7,849
每次读取文件长度8k,每次写入文件长度不定,文件操作已经大大减少。
3、extractNIO
23945 14:08:55.0475907 java.exe 480 QueryStandardInformationFile D:\temp\eoshome.zip SUCCESS AllocationSize: 38,592,512, EndOfFile: 38,592,090, NumberOfLinks: 1, DeletePending: False, Directory: False
23946 14:08:55.0476046 java.exe 480 ReadFile D:\temp\eoshome.zip SUCCESS Offset: 1,335,296, Length: 8,192
23947 14:08:55.0477401 java.exe 480 WriteFile D:\temp\temp\base\lib\3rd\ant.jar FAST IO DISALLOWED Offset: 8,192, Length: 8,192
23948 14:08:55.0477516 java.exe 480 WriteFile D:\temp\temp\base\lib\3rd\ant.jar SUCCESS Offset: 8,192, Length: 8,192
23949 14:08:55.0480365 java.exe 480 QueryStandardInformationFile D:\temp\eoshome.zip SUCCESS AllocationSize: 38,592,512, EndOfFile: 38,592,090, NumberOfLinks: 1, DeletePending: False, Directory: False
23950 14:08:55.0480505 java.exe 480 ReadFile D:\temp\eoshome.zip SUCCESS Offset: 1,343,488, Length: 8,192
23951 14:08:55.0481932 java.exe 480 WriteFile D:\temp\temp\base\lib\3rd\ant.jar SUCCESS Offset: 16,384, Length: 8,192
采用NIO channel之后,每次读写均为8k,对于IO的压力应该算比较小了。
观察java的IO操作用的是Systeminternals的Process Monitor,有兴趣的tx可以试试
del.icio.us Tags:
java
,
performance