简单的java io测试

作者: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: ,

posted on 2007-09-20 14:27 tacy lee 阅读(1549) 评论(4)  编辑  收藏 所属分类: 性能相关

评论

# re: 简单的java io测试[未登录] 2007-09-20 14:53 javacap

zis.getNextEntry() do more things than you think.To use zipFile.entries() may get better permanence.  回复  更多评论   

# re: 简单的java io测试 2007-09-20 15:00 tacy lee

呵呵 用zipfile应该能更快一点  回复  更多评论   

# re: 简单的java io测试 2007-09-20 16:20 千里冰封

呵呵,楼主可以把代码放到代码框里,这样更好看一些  回复  更多评论   

# re: 简单的java io测试[未登录] 2007-09-20 18:09 tacy lee

;) 修改了一下排版,加了ZipFile方法,简单测试了一下,和extractnio差不多  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航: