Распаковка файла, содержащего другие файлы Zip - PullRequest
0 голосов
/ 02 июля 2010

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

Моя единственная трудность заключается в том, что когда запись сама является файлом 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);
  }
 }

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

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

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

1 Ответ

0 голосов
/ 03 июля 2010

Я не знаю точно, что вы делаете с вашими размерами, я думаю, вы действительно запутались. 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));
        }
    }
}
...