2010-07-02 2 views
0

Я пытаюсь разархивировать файлы, содержащие другие zip-файлы. Моя попытка основана на следующем коде Java2s: http://www.java2s.com/Code/Java/File-Input-Output/LoadresourcefromJarfile.htm.Разархивировать файл, который содержит другие почтовые файлы

Моя единственная трудность заключается в том, что, когда запись сама по себе является файлом Jar, я не могу ее разархивировать, не записывая сначала в файл temp.

Вот что я делаю:

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); 
    } 
} 

Что я вижу остроумие второй версии является то, что размер информация о входах, содержащихся во внутренних банках, доступна только в том случае, если я сначала напишу эту внутреннюю банку на диск.

есть ли способ избежать этого?

Большое спасибо, Klaus.

+0

пожалуйста, используйте код кавычки, это делает все гораздо более удобным для чтения. – user29964

+0

Это ваш первый вопрос, но вы, возможно, заметили, как выглядят «компактные» примеры кода. Вы должны посмотреть FAQ по форматированию вашего вопроса. Особенно отступают строки кода с четырьмя пробелами, чтобы их правильно отформатировать. – Stroboskop

+0

Спасибо, я сделаю это. Приносим извинения за неудобства. – Klaus

ответ

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

Смежные вопросы