首页 文章

在Java中解压缩错误

提问于
浏览
3

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

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

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

这是我的本机java实现的代码:

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代码为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文件解压缩到文件系统中,请让我知道它是如何完成的 .

编辑1:

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

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

编辑2:

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

编辑后的代码将粘贴在下方,以供将来使用它的任何人使用 .

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

如果有人知道一种方法来跳过额外的字节我都是耳朵:)

2 回答

  • 0

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

    跳过空字节的天真方式是继续读取,直到遇到'PK'签名 . 因此在程序中,输入流读取字节,直到它达到'PK'为止,然后它启动Zip inputStream并传递后面的字节流 .

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

    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();
    
        }
    
  • 2

    什么是确切的异常消息?

    请注意,ZIP文件可能存在格式差异 . 例如:您使用加密吗?这对于内置的java例程来说是个问题 .

    并且:您是否尝试使用其他ZIP工具重新打包?

相关问题