Unzip error in Java

£可爱£侵袭症+ 提交于 2020-06-15 21:24:29

问题


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.

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

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.

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

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

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.

EDIT 1:

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

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

EDIT 2:

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 :)


回答1:


Finally solved the issue , with help of my friend ,

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

    }



回答2:


What is the exact Exception message?

Note that there can be format differences on ZIP files. For example: Did you use encryption? This would be a problem for the built-in java routine.

And: Did you try a repack with another ZIP tool?



来源:https://stackoverflow.com/questions/13788373/unzip-error-in-java

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!