2010-07-02 81 views
0

我想解壓縮包含其他zip文件的文件。我的嘗試基於以下Java2代碼:http://www.java2s.com/Code/Java/File-Input-Output/LoadresourcefromJarfile.htmUnziping包含其他Zip文件的文件

我唯一的困難是,當一個條目本身就是一個Jar文件時,我無法首先將其解壓縮到臨時文件中。

下面是我在做什麼:

public void load(String jarFileName) throws Exception{ 
    ZipFile zf = new ZipFile(jarFileName); 
    load(zf.entries(),new FileInputStream(jarFileName),zf.size()); 
} 
public void load(Enumeration<? extends ZipEntry> enumeration, InputStream    inputStream, int total) throws Exception { 
    if(enumeration!=null){ 
    while (enumeration.hasMoreElements()) { 
    ZipEntry ze = (ZipEntry) enumeration.nextElement(); 
    htSizes.put(ze.getName(), new Integer((int) ze.getSize())); 
    } 
    } 

    BufferedInputStream bis = new BufferedInputStream(inputStream); 
    ZipInputStream zis = new ZipInputStream(bis); 
    ZipEntry ze = null; 
    int retrieved=0; 
    while ((ze = zis.getNextEntry()) != null) { 
    if (ze.isDirectory()) { 
    continue; 
    } 
    int size = (int) ze.getSize(); 
    if (size == -1 && htSizes.get(ze.getName())!=null) { 
    size = ((Integer) htSizes.get(ze.getName())).intValue(); 
    } 
    if(size==-1) 
    size=total-retrieved; 
    retrieved+=size; 
    byte[] b = new byte[(int) size]; 
    int rb = 0; 
    int chunk = 0; 
    while (((int) size - rb) > 0) { 
    chunk = zis.read(b, rb, (int) size - rb); 
    if (chunk == -1) { 
    break; 
    } 
    rb += chunk; 
    } 
    if(ze.getName().endsWith(".jar")){ 
    File f=File.createTempFile("temp", System.nanoTime()+""); 
    f.deleteOnExit(); 
    FileOutputStream fos= new FileOutputStream(f); 
    fos.write(b); 
    fos.close(); 
    load(f.getAbsolutePath()); 
    } 

    else htJarContents.put(ze.getName(), b); 
    } 
} 

我真正想做的事情,但是是這樣的:

public void load(String jarFileName) throws Exception{ 
    ZipFile zf = new ZipFile(jarFileName); 
    load(zf.entries(),new FileInputStream(jarFileName),zf.size()); 
} 
public void load(Enumeration<? extends ZipEntry> enumeration, InputStream inputStream, int total) throws Exception { 
    if(enumeration!=null){ 
    while (enumeration.hasMoreElements()) { 
    ZipEntry ze = (ZipEntry) enumeration.nextElement(); 
    htSizes.put(ze.getName(), new Integer((int) ze.getSize())); 
    } 
    } 

    BufferedInputStream bis = new BufferedInputStream(inputStream); 
    ZipInputStream zis = new ZipInputStream(bis); 
    ZipEntry ze = null; 
    int retrieved=0; 
    while ((ze = zis.getNextEntry()) != null) { 
    if (ze.isDirectory()) { 
    continue; 
    } 
    int size = (int) ze.getSize(); 
    if (size == -1 && htSizes.get(ze.getName())!=null) { 
    size = ((Integer) htSizes.get(ze.getName())).intValue(); 
    } 
    if(size==-1) 
    size=total-retrieved; 
    retrieved+=size; 
    byte[] b = new byte[(int) size]; 
    int rb = 0; 
    int chunk = 0; 
    while (((int) size - rb) > 0) { 
    chunk = zis.read(b, rb, (int) size - rb); 
    if (chunk == -1) { 
    break; 
    } 
    rb += chunk; 
    } 
    if(ze.getName().endsWith(".jar")){ 
    load(null,new ByteArrayOutputstream(b)); 
    } 
    else htJarContents.put(ze.getName(), b); 
    } 
} 

我所看到的機智的第二個版本是大小包含在內部容器中的條目的信息僅在我首先將該內部容器寫入磁盤時纔可用。

有沒有辦法避免這種情況?

非常感謝, 克勞斯。

+0

請用代碼的報價,這使得一切都更具可讀性。 – user29964 2010-07-02 12:39:17

+0

這是你的第一個問題,但你可能已經注意到你的代碼示例看起來很「緊湊」了。您應該查看有關格式化問題的常見問題解答。尤其是具有四個空格的縮進代碼行可以正確格式化它們。 – Stroboskop 2010-07-02 12:41:32

+0

謝謝,我會這樣做的。抱歉給你帶來不便。 – Klaus 2010-07-02 12:46:08

回答

0

我不確切地知道你在用你的尺碼做什麼,我想你會讓他們感到困惑。 ZipInputStream.getNextEntry()將流定位在條目的開頭。從http://java.sun.com/javase/6/docs/api/java/util/zip/ZipInputStream.html#getNextEntry()

公衆的ZipEntry getNextEntry()拋出IOException異常

讀取下一個ZIP文件 條目,位置在 開始進入數據流。

所以,我下面的作品:

public void process(String filename) throws IOException { 
    process(filename, new FileInputStream(new File(filename))); 
} 

private void process(String filename, InputStream inputStream) throws IOException { 
    ZipInputStream zis = new ZipInputStream(inputStream); 
    ZipEntry ze = null; 

    while ((ze = zis.getNextEntry()) != null) { 
     if (ze.isDirectory()) { 
      continue; 
     } 

     System.out.println(ze.getName() + " " + ze.getSize()); 

     if (ze.getName().endsWith(".jar")) { 
      long size = ze.getSize(); 

      byte[] b = new byte[(int) size]; 

      int rb = 0; 
      int chunk = 0; 
      while (((int) size - rb) > 0) { 
       chunk = zis.read(b, rb, (int) size - rb); 
       if (chunk == -1) { 
        break; 
       } 
       rb += chunk; 
      } 

      process(ze.getName(), new ByteArrayInputStream(b)); 
     } 
    } 
} 
+0

謝謝你馬特。它似乎工作。不知道爲什麼我getSize()返回-1。 – Klaus 2010-07-04 01:09:35

相關問題