解压缩包含其他 Zip 文件的文件

发布于 2024-09-08 03:44:18 字数 3304 浏览 3 评论 0原文

我正在尝试解压缩包含其他 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);
  }
 }

我在第二个版本中看到的是,仅当我编写此内部时,内部罐子中包含的条目的大小信息才可用首先将 jar 复制到磁盘上。

有办法避免这种情况吗?

非常感谢, 克劳斯。

I'm trying to unzip a files that contain other zip files. My attempt is based on the following Java2s code: http://www.java2s.com/Code/Java/File-Input-Output/LoadresourcefromJarfile.htm.

My only difficulty is that when an entry is itself a Jar file, I'm not able to unzip it without writing it to a temp file first.

Here is what I'm doing:

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

What I really want to do, however is this:

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

What I'm seeing wit the second version is that the size information of the entries contained in the inner-jars are available only if I write this inner jar to a the disk first.

is there a way to avoid this?

Thanks so much,
Klaus.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我ぃ本無心為│何有愛 2024-09-15 03:44:18

我不知道你到底在用你的尺寸做什么,我认为你让它们真的很困惑。 ZipInputStream.getNextEntry() 将流定位在条目的开头。来自 http://java .sun.com/javase/6/docs/api/java/util/zip/ZipInputStream.html#getNextEntry()

public ZipEntry getNextEntry() 抛出异常
IO异常

读取下一个 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));
        }
    }
}

I don't know exactly what you're doing with your sizes, I think you're getting them really confused. ZipInputStream.getNextEntry() positions the stream at the beginning of the entry. From http://java.sun.com/javase/6/docs/api/java/util/zip/ZipInputStream.html#getNextEntry()

public ZipEntry getNextEntry() throws
IOException

Reads the next ZIP file
entry and positions stream at the
beginning of the entry data.

So, the following works for me:

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));
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文