opike
opike

Reputation: 7585

Java: unzipping is significantly slower than zipping

I have some code that zips up a file sends it over the network and then unzips it on the other end. I'm still testing the code and the source and the destination are the same. Zipping up the file takes on the order of a minute. Unzipping the file takes on the order of an hour. I'm think there must be a flaw in my code to have such a large difference. Here's the code to unzip:

public String uncompressLocalZip(String filename,String strUUID,ParentEntry pe,boolean bControlFileProgress) {
        final int BUFFER = 2048;
        BufferedOutputStream out  = null;
        ZipInputStream zis = null;

        try {

            FileInputStream fis = new FileInputStream(Constants.conf.getFileDirectory() + Constants.PATH_SEPARATOR + strUUID + Constants.PATH_SEPARATOR + filename);
            zis = new  ZipInputStream(new BufferedInputStream(fis));
            ZipEntry entry;
            long totallength = 0;
            long size = 0;
            if (pe !=null)
                size = pe.getSize();


            while((entry = zis.getNextEntry()) != null) {
                System.out.println("Extracting: " +entry);
                int count;
                byte data[] = new byte[BUFFER];
                // write the files to the disk

                File fileOutput = new File(Constants.conf.getFileDirectory() + Constants.PATH_SEPARATOR + strUUID + Constants.PATH_SEPARATOR + Constants.conf.getUncompressFolderName() + Constants.PATH_SEPARATOR + entry.getName());
                new File(fileOutput.getParent()).mkdirs();


                BufferedOutputStream fos = new BufferedOutputStream(new FileOutputStream(fileOutput));

                out = new BufferedOutputStream(fos, BUFFER);
                while ((count = zis.read(data, 0, BUFFER)) != -1) {
                       out.write(data, 0, count);
                       totallength += count;

            }
            out.flush();

        }

     }
     catch(Exception e) {
        e.printStackTrace();
        return("FAILED");
     }
     finally {
        try {if ( out!= null) out.close();} catch (IOException ioe) {}
        try {if ( zis!= null) zis.close();} catch (IOException ioe) {}

     }

    return("SUCCESS");      



}

Here's the code to zip:

public void createLocalZip(String filename,ProcessEntry pe) {
    ZipOutputStream out=null;
    try {

        File fileOutput = new File (filename);
        out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(fileOutput)));
        long totallength=0;
        long size = pe.getParentEntry().getSize();

        String strStartDirectory;
        if (pe.getParentEntry().isDirectory())
            strStartDirectory=pe.getParentEntry().getUrl();
        else
            strStartDirectory=pe.getParentEntry().getFolder();



        for (int i=0;i<pe.getParentEntry().tableModel3.getRowCount();i++) {
            FileEntry fe = pe.getParentEntry().tableModel3.getFileEntry(i);
            File fileInput = new File (fe.getUrl());
            FileInputStream input = new FileInputStream(fileInput);
            BufferedInputStream in = new BufferedInputStream(input);

            String strRelativeDir = fe.getUrl().substring(strStartDirectory.length()+1,fe.getUrl().length());

            ZipEntry entry = new ZipEntry(strRelativeDir);

            out.putNextEntry(entry);


            byte[] bbuf = new byte[2048];
            int length=0;




             while ((in != null) && ((length = in.read(bbuf)) != -1)) {

                    out.write(bbuf,0,length);
                    totallength += length;
                    pe.setProgress((int) (totallength*100/size));

             }

             in.close();


        }






    }
    catch (Exception e) {
        System.out.println(e.getMessage());
    }
    finally {
        try {if (out!=null) out.close();} catch(IOException ioe){}
    }


}

Update: The compression ratio for this particular test is about 90% (1.2GB down to about 100MB). So I suppose it could be the extra writing to disk for unzipping vs. zipping, although I would expect close to a 10X differential vs 60X.

Upvotes: 2

Views: 978

Answers (3)

Dorus
Dorus

Reputation: 7546

Consider using a specialized library to do the zipping/unzipping. http://sevenzipjbind.sourceforge.net/ might help.

Upvotes: 0

jtahlborn
jtahlborn

Reputation: 53694

don't double wrap your OutputStream with BufferedOutputStream (you only need 1 BufferedOutputStream wrapper), and close it after you are done writing to it.

also, ZipEntrys can be directories, so check that and handle accordingly.

Upvotes: 2

Paŭlo Ebermann
Paŭlo Ebermann

Reputation: 74750

I have no really big file to test your code, so I can only guess.

  1. You say your uncompressed zip size is more than 1 GB. This could be more than fits in your memory, and if something forces the VM to fit everything in memory, it will have to swap. Observe your program with a profiler.

  2. Make sure your close each FileOutputStream after writing to it. (You create lots of them, and only close the last one.)

  3. I'm not sure about the ZipInputStream implementation (maybe it forces your BufferedStream to buffer much of data). You could try ZipFile instead (which allows random access, basically).

Upvotes: 0

Related Questions