0

I want to extract two specific files from a .zip file. I tried the following library:

ZipFile zipFile = new ZipFile("myZip.zip");

Result:

Exception in thread "main" java.util.zip.ZipException: error in opening zip file

I also tried:

public void extract(String targetFileName) throws IOException
{
    OutputStream outputStream = new FileOutputStream("targetFile.foo");
    FileInputStream fileInputStream = new FileInputStream("myZip.zip");
    ZipInputStream zipInputStream = new ZipInputStream(new BufferedInputStream(fileInputStream));
    ZipEntry zipEntry;

    while ((zipEntry = zipInputStream.getNextEntry()) != null)
    {
        if (zipEntry.getName().equals("targetFile.foo"))
        {
            byte[] buffer = new byte[8192];
            int length;
            while ((length = zipInputStream.read(buffer)) != -1)
            {
                outputStream.write(buffer, 0, length);
            }
            outputStream.close();
            break;
        }
    }
}

Result:
No exception, but an empty targetFile.foo file.

Note that the .zip file is of type SFX 7-zip and initially had the .exe extensions so that may be the reason for the failure.

BullyWiiPlaza
  • 17,329
  • 10
  • 113
  • 185
  • Does it work with regluar zip files? – f1sh Feb 27 '16 at 14:04
  • 1
    That format is not compatible with `ZipInputStream`. See [this answer](http://stackoverflow.com/questions/5481487/how-to-use-lzma-sdk-to-compress-decompress-in-java#9186639) – Reimeus Feb 27 '16 at 14:06

1 Answers1

0

As in Comments, Extracting SFX 7-Zip file is basically not supported with your library. But you can do with commons compress and xz Libary together with a quick "hack":

import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
...
  protected File un7zSFXFile(File file, String password)
      {
        SevenZFile sevenZFile = null;
        File tempFile = new File("/tmp/" + file.getName() + ".temp");
        try
        {
          FileInputStream in = new FileInputStream(file);
          /**
           * Yes this is Voodoo Code:
           * first 205824 Bytes get skipped as these is are basically the 7z-sfx-runnable.dll
           * common-compress does fail if this information is not cut away
           * ATTENTION: the amount of bytes may vary depending of the 7z Version used!
           */
          in.skip(205824);
          // EndOfVoodoCode
          tempFile.getParentFile().mkdirs();
          tempFile.createNewFile();
          FileOutputStream temp = new FileOutputStream(tempFile);
          byte[] buffer = new byte[1024];
          int length;
          while((length = in.read(buffer)) > 0)
          {
            temp.write(buffer, 0, length);
          }
          temp.close();
          in.close();
          LOGGER.info("prepared exefile for un7zing");
          if (password!=null) {
          sevenZFile = new SevenZFile(tempFile, password.toCharArray());
          } else {
            sevenZFile = new SevenZFile(tempFile);
          }
          SevenZArchiveEntry entry;
          boolean first = true;// accept only files with
          while((entry = sevenZFile.getNextEntry()))
          {
            if(entry.isDirectory())
            {
              continue;
            }
            File curfile = new File(file.getParentFile(), entry.getName());
            File parent = curfile.getParentFile();
            if(!parent.exists())
            {
              parent.mkdirs();
            }
            FileOutputStream out = new FileOutputStream(curfile);
            byte[] content = new byte[(int) entry.getSize()];
            sevenZFile.read(content, 0, content.length);
            out.write(content);
            out.close();
          }
        }
        catch(Exception e)
        {          
          throw e;
        }
        finally
        {
          try
          {
            tempFile.delete();
            sevenZFile.close();
    
          }
          catch(Exception e)
          {
            LOGGER.trace("error on cloasing Stream: " + sevenZFile.getDefaultName(), e);
          }
        }
      }

Please acknowledge that this simple solution does only unpack in to the same directory as the as sfx-file is placed!