2011-06-17 375 views
2

我有一些将文件压缩的​​代码通过网络发送,然后在另一端解压缩。我仍在测试代码,并且源和目标都相同。压缩文件需要一分钟的时间。解压缩文件需要一个小时。我认为我的代码中必然存在一个缺陷,以产生如此大的差异。下面的代码来解压缩:Java:解压缩明显慢于压缩

public String uncompressLocalZip(String filename,String strUUID,ParentEntry pe,boolean bControlFileProgress) { 
     final int BUFFER = 2048; 
     BufferedOutputStream out = null; 
     ZipInputStream zis = null; 

     try { 

      FileInputStream fis = new FileInputStream(Constants.conf.getFileDirectory() + Constants.PATH_SEPARATOR + strUUID + Constants.PATH_SEPARATOR + filename); 
      zis = new ZipInputStream(new BufferedInputStream(fis)); 
      ZipEntry entry; 
      long totallength = 0; 
      long size = 0; 
      if (pe !=null) 
       size = pe.getSize(); 


      while((entry = zis.getNextEntry()) != null) { 
       System.out.println("Extracting: " +entry); 
       int count; 
       byte data[] = new byte[BUFFER]; 
       // write the files to the disk 

       File fileOutput = new File(Constants.conf.getFileDirectory() + Constants.PATH_SEPARATOR + strUUID + Constants.PATH_SEPARATOR + Constants.conf.getUncompressFolderName() + Constants.PATH_SEPARATOR + entry.getName()); 
       new File(fileOutput.getParent()).mkdirs(); 


       BufferedOutputStream fos = new BufferedOutputStream(new FileOutputStream(fileOutput)); 

       out = new BufferedOutputStream(fos, BUFFER); 
       while ((count = zis.read(data, 0, BUFFER)) != -1) { 
         out.write(data, 0, count); 
         totallength += count; 

      } 
      out.flush(); 

     } 

    } 
    catch(Exception e) { 
     e.printStackTrace(); 
     return("FAILED"); 
    } 
    finally { 
     try {if (out!= null) out.close();} catch (IOException ioe) {} 
     try {if (zis!= null) zis.close();} catch (IOException ioe) {} 

    } 

    return("SUCCESS");  



} 

下面的代码到拉链:

public void createLocalZip(String filename,ProcessEntry pe) { 
    ZipOutputStream out=null; 
    try { 

     File fileOutput = new File (filename); 
     out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(fileOutput))); 
     long totallength=0; 
     long size = pe.getParentEntry().getSize(); 

     String strStartDirectory; 
     if (pe.getParentEntry().isDirectory()) 
      strStartDirectory=pe.getParentEntry().getUrl(); 
     else 
      strStartDirectory=pe.getParentEntry().getFolder(); 



     for (int i=0;i<pe.getParentEntry().tableModel3.getRowCount();i++) { 
      FileEntry fe = pe.getParentEntry().tableModel3.getFileEntry(i); 
      File fileInput = new File (fe.getUrl()); 
      FileInputStream input = new FileInputStream(fileInput); 
      BufferedInputStream in = new BufferedInputStream(input); 

      String strRelativeDir = fe.getUrl().substring(strStartDirectory.length()+1,fe.getUrl().length()); 

      ZipEntry entry = new ZipEntry(strRelativeDir); 

      out.putNextEntry(entry); 


      byte[] bbuf = new byte[2048]; 
      int length=0; 




      while ((in != null) && ((length = in.read(bbuf)) != -1)) { 

        out.write(bbuf,0,length); 
        totallength += length; 
        pe.setProgress((int) (totallength*100/size)); 

      } 

      in.close(); 


     } 






    } 
    catch (Exception e) { 
     System.out.println(e.getMessage()); 
    } 
    finally { 
     try {if (out!=null) out.close();} catch(IOException ioe){} 
    } 


} 

更新:对于该特定试验中的压缩比为约90%(1.2GB到大约100MB)。所以我想这可能是额外写入磁盘解压缩与压缩,虽然我预计接近10倍差距与60倍。

+2

你有没有尝试过分析你的解压缩代码? – 2011-06-17 01:08:53

+0

从命令行(jar或unzip)运行它时,解压缩同一文件需要多长时间? – Thilo 2011-06-17 01:10:36

+1

另外,请尝试观察内存使用情况。难道你的系统交换的太多了,因为你的文件不适合内存,并且不知怎的,你的程序试图把它放在那里? – 2011-06-17 01:15:18

回答

2

不要使用BufferedOutputStream(您只需要1个BufferedOutputStream包装器)对OutputStream进行双重包装,并在完成写入后关闭它。

也,ZipEntry s可以是目录,所以检查并相应地处理。

+0

几乎所有我见过的例子都建议使用缓冲输出流(如这个http://www.javadb.com/write-to-file-using-bufferedoutputstream),否则文件I/O效率不高(我认为每次写入磁盘时都会有一些开销,并且缓冲会减少开销)。 – opike 2011-06-17 02:09:47

+0

@opike - 你正在使用_2_ BufferedOutputStreams,你只需要_1_。 – jtahlborn 2011-06-17 11:26:32

+0

缓冲两次不应导致较慢的输入读数。原因必须在别处。 – 2014-03-07 19:31:40

0

我没有真正大的文件来测试你的代码,所以我只能猜测。

  1. 你说你的未压缩的zip大小超过1 GB。这可能不仅仅是适合你的记忆,而且如果有东西强迫VM将内存中的所有内容都包含进来,它将不得不交换。用探查器观察你的程序。

  2. 确保在写入之后关闭每个FileOutputStream。 (你创建它们很多,只关闭最后一个。)

  3. 我不确定ZipInputStream的实现(可能会强制你的BufferedStream缓冲大部分数据)。您可以尝试使用ZipFile(基本上允许随机访问)。