Java解压错误 [英] Unzip error in Java

查看:44
本文介绍了Java解压错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 zip 格式很陌生,我使用 Java 的 util 实现来解压缩文件,但是每次我尝试打开文件时它都会抛出一个 ZipException.我检查了文件是否已损坏,这不是因为我可以使用 winRar 打开它.

Hi I am quite new to zip format, and I used the Java's util implementation to unzip a file, However it throws a ZipException everytime I try to open the file. I checked to see if the file was corrupted and it is not because I can open it using winRar.

所以我继续尝试 appache.commons.vfs 包来做同样的事情,但这也导致了失败.

So I moved on and tried appache.commons.vfs package to do the same thing and that too resulted in a failure.

作为最后的尝试,我尝试了 7-zip-jbinding 库,它能够读取 Zip 存档的内容,但我无法提取它.

As a final try I tried the library 7-zip-jbinding and that is able to read the contents of the Zip archive but I am not able to extract it.

这是我的原生 java 实现代码:

Here is my code for native java implementation:

BufferedOutputStream dest = null;
    FileInputStream fis = new FileInputStream(archive);
    ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
    ZipEntry entry;
    File destFile;

    destinationDir.mkdir();

    while ((entry = zis.getNextEntry()) != null) {

        String currentfileName = entry.getName();
        destFile = new File(destinationDir, currentfileName);
        File destinationParent = destFile.getParentFile();

        destinationParent.mkdirs();

        if (!entry.isDirectory()) {
            int currentByte;
            byte data[] = new byte[BUFFER_SIZE];

            FileOutputStream fos = new FileOutputStream(destFile);
            dest = new BufferedOutputStream(fos, BUFFER_SIZE);

            while ((currentByte = zis.read(data, 0, BUFFER_SIZE)) != -1) {
                dest.write(data, 0, currentByte);
            }
            dest.flush();
            dest.close();

        }
    }
    fis.close();
    zis.close(); 

我的 appache commons vfs 代码

My code for appache commons vfs

 public void unpack(final File outputDir,URI packLocation) throws IOException
   {
 this.packLocation = packLocation;
 this.fileSystemManager = VFS.getManager();

 outputDir.mkdirs();

  final FileObject packFileObject =   fileSystemManager.resolveFile(packLocation.toString());
  try
  {
     final FileObject zipFileSystem = fileSystemManager.createFileSystem(packFileObject);
     try
     {
        fileSystemManager.toFileObject(outputDir).copyFrom(zipFileSystem, new AllFileSelector());
     }
     finally
     {
        zipFileSystem.close();
     }
  }
  finally
  {
     packFileObject.close();
  }
 }

有什么很明显的东西我遗漏了吗?如果有人使用 7-zip-jbinding 将 zip 文件解压缩到文件系统中,请告诉我它是如何完成的.

Is there something very obvious that I am missing? And if anyone has used 7-zip-jbinding for extracting a zip file into file system please do let me know how it is done.

编辑 1:

在该文件的 mac 终端中执行解压缩时,它向我显示了以下警告

While executing a unzip in mac terminal of that file it showed me the following warning

警告:在 zipfile 开头或内部有 84 个额外字节..这会以某种方式影响 Zip 输入流吗?

warning : 84 extra bytes at beginning or within zipfile .. Can this somehow affect Zip input Stream ?

编辑 2:

zip 文件中的 extrabytes 似乎搞砸了 zip 输入流.. 在终端上使用 unzip 会显示添加到 zip 文件中的额外字节数.我使用 RandomAccessFile 跳过 (n) 个字节并且 Zip 输入流开始正常工作.. 现在我需要做的就是找到一种方法来删除 Zip 文件中的额外字节..

The extrabytes in the zip file seemed to screw up the zip input stream .. Using unzip on the terminal shows the number of extra bytes that are added to the zip file . I Used a RandomAccessFile to skip (n) bytes and the Zip Input Stream Started working fine .. Now all i need to do is find a way to remove the extra bytes in Zip File ..

编辑后的代码粘贴在下面,供将来从中受益的任何人使用.

The edited code is pasted below for anyone who would benifit from it in the future .

    final int BUFFER_SIZE = 1024;

    RandomAccessFile randomAccessFile = new RandomAccessFile(archive, "r");
    randomAccessFile.skipBytes(84); // The extra bytes 

    FileChannel channel = randomAccessFile.getChannel();

    BufferedOutputStream dest = null;
    ZipInputStream zis = new ZipInputStream(new BufferedInputStream(Channels.newInputStream(channel)));
    ZipEntry entry;
    File destFile;

    destinationDir.mkdir();

    while ((entry = zis.getNextEntry()) != null) {

        String currentfileName = entry.getName();
        destFile = new File(destinationDir, currentfileName);
        File destinationParent = destFile.getParentFile();

        destinationParent.mkdirs();

        if (!entry.isDirectory()) {
            int currentByte;
            byte data[] = new byte[BUFFER_SIZE];

            FileOutputStream fos = new FileOutputStream(destFile);
            dest = new BufferedOutputStream(fos, BUFFER_SIZE);
            while ((currentByte = zis.read(data, 0, BUFFER_SIZE)) != -1) {
                dest.write(data, 0, currentByte);
            }
            dest.flush();
            dest.close();

        }
    }
    zis.close();

如果有人知道跳过额外字节的方法,我全听:)

If anyone knows a way to skip the extra bytes I am all ears :)

推荐答案

终于在朋友的帮助下解决了问题,

Finally solved the issue , with help of my friend ,

跳过空字节的天真方法是继续阅读直到遇到PK"签名.因此,在程序中,输入流会读取字节,直到遇到PK"为止,然后它会初始化 Zip inputStream 并传递后面的字节流.

The naive way of skipping the empty bytes is to keep reading till the 'PK' signature is encountered . So in the program an input stream reads the bytes till it hits the 'PK' once it does then it initiliases the Zip inputStream and passes the stream of bytes that follow .

下面是快速而肮脏的方式.将会有比这更优雅的解决方案......但目前这是有效的.

Below is the quick and dirty way . There will be more elegant solutions than this .. but for the moment this works .

 InputStream zipStarterStream, emptyBytecountStream;
    ZipInputStream zis;
    int BUFFER = 2048;

    /* Primary Checking to see if there is a zip file */
    File file = new File(filePath);
    if (file.exists()) {
        System.out.println("Zip found");
    } else {
        System.out.println("Zip Not found");
        return;
    }
    try {
        emptyBytecountStream = new FileInputStream(filePath);
        Charset encoding = Charset.defaultCharset();
        Reader reader = new InputStreamReader(emptyBytecountStream,
                encoding);
        int r1, r2;
        int charSkipped = 0;
        boolean foundHeader = false;

        // This is the check to skip the initial few bytes

        while ((r1 = reader.read()) != -1 && (r2 = reader.read()) != -1) {
            char ch1 = (char) r1;
            char ch2 = (char) r2;
            if (ch1 == 'P' && ch2 == 'K') {
                foundHeader = true;
                break;
            }
            charSkipped += 2;
        }
        emptyBytecountStream.close();

        zipStarterStream = new FileInputStream(filePath);
        zis = new ZipInputStream(new BufferedInputStream(zipStarterStream));

        if (foundHeader && charSkipped > 0) {
            zipStarterStream.skip(charSkipped);
        }

        String outputPath = getPublicStorageDir("")
                + "/"
                + filePath.substring(filePath.lastIndexOf("/") + 1,
                        filePath.length());

        new File(outputPath).mkdir();
        ZipEntry entry;

        while ((entry = zis.getNextEntry()) != null) {

            String currentfileName = entry.getName();
            File destFile = new File(outputPath, currentfileName);
            File destinationParent = destFile.getParentFile();

            destinationParent.mkdirs();

            if (!entry.isDirectory()) {
                int currentByte;
                byte data[] = new byte[BUFFER];

                // write the current file to disk
                FileOutputStream fos = new FileOutputStream(destFile);
                BufferedOutputStream dest = new BufferedOutputStream(fos,
                        BUFFER);

                // read and write until last byte is encountered
                while ((currentByte = zis.read(data, 0, BUFFER)) != -1) {
                    dest.write(data, 0, currentByte);
                }
                dest.flush();
                dest.close();
            }

            if (currentfileName.endsWith(".zip")) {
                extractZipFolder(destFile.getAbsolutePath());
            }
        }
        zis.close();
    } catch (IOException e) {
        e.printStackTrace();

    }

这篇关于Java解压错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆