tags:

views:

74

answers:

3

Hi

I'd like to do something like this in my program:

File zipFile = .....;
File destDir = ....;    
ImaginaryZipUtility.unzipAllTo(zipFile, destdir);

I cannot possibly be the first to do this from a program. Where do I find a utility method like above? I tried to look at apache commons-io, but nothing there. So, where should I look?

+2  A: 

Well, java.util.zip has classes to do what you want in a very straighforward way

helios
I know, but that is not what I meant. See comment on answer by jsshah below.
eirikma
+2  A: 

very old code that I was able to dig up

package com.den.frontend;

import java.util.; import java.util.zip.; import java.io.*;

public class ZIPUtility 
{
    public static final int BUFFER_SIZE = 2048;

    //This function converts the zip file into uncompressed files which are placed in the 
    //destination directory
    //destination directory should be created first
    public static boolean unzipFiles(String srcDirectory, String srcFile, String destDirectory)
    {
        try
        {
            //first make sure that all the arguments are valid and not null
            if(srcDirectory == null)
            {
                System.out.println(1);
                return false;
            }
            if(srcFile == null)
            {
                System.out.println(2);
                return false;
            }
            if(destDirectory == null)
            {
                System.out.println(3);
                return false;
            }
            if(srcDirectory.equals(""))
            {
                System.out.println(4);
                return false;
            }
            if(srcFile.equals(""))
            {   
                System.out.println(5);
                return false;
            }
            if(destDirectory.equals(""))
            {
                System.out.println(6);
                return false;
            }
            //now make sure that these directories exist
            File sourceDirectory = new File(srcDirectory);
            File sourceFile = new File(srcDirectory + File.separator + srcFile);
            File destinationDirectory = new File(destDirectory);

            if(!sourceDirectory.exists())
            {
                System.out.println(7);
                return false;
            }
            if(!sourceFile.exists())
            {
                System.out.println(sourceFile);
                return false;
            }
            if(!destinationDirectory.exists())
            {
                System.out.println(9);
                return false;
            }

            //now start with unzip process
            BufferedOutputStream dest = null;

            FileInputStream fis = new FileInputStream(sourceFile);
            ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));

            ZipEntry entry = null;

            while((entry = zis.getNextEntry()) != null)
            {
                String outputFilename = destDirectory + File.separator + entry.getName();

                System.out.println("Extracting file: " + entry.getName());

                createDirIfNeeded(destDirectory, entry);

                int count;

                byte data[] = new byte[BUFFER_SIZE];

                //write the file to the disk
                FileOutputStream fos = new FileOutputStream(outputFilename);
                dest = new BufferedOutputStream(fos, BUFFER_SIZE);

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

                //close the output streams
                dest.flush();
                dest.close();
            }

            //we are done with all the files
            //close the zip file
            zis.close();

        }
        catch(Exception e)
        {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    private static void createDirIfNeeded(String destDirectory, ZipEntry entry)
    {
        String name = entry.getName();

        if(name.contains("/"))
        {
            System.out.println("directory will need to be created");

            int index = name.lastIndexOf("/");
            String dirSequence = name.substring(0, index);

            File newDirs = new File(destDirectory + File.separator + dirSequence);

            //create the directory
            newDirs.mkdirs();
        }
    }

}
jsshah
thanks, both of you, but that is not what I meant. I know it is possible to traverse zip entries, create the necessary directories and so and so using the std api. I don't want all that in my program. It's too much code: it's ugly and confusing. It shouldn't be necessary for all programs that wants to unzip files to include all that stuff. I want a single-line command to unzip an archive, just like you would do on the command line. It is hard to believe the ZipFile class doesn't have a unzipTo(directory) method. Instead it requires 50 lines to do the same. What's that for API design?
eirikma
hmm. Perhaps I should try this:Runtime.getRuntime().exec(new String[]{ "unzip", zipfile.getAbsolutePath(), "-d", destdir.getAbsolutePath(), });
eirikma
The advantage of using a JavaClass is portability (you don't have to worry about native binaries)
helios
Why dont you add the code above as a class into your project? then you'll have a oneline solution! i.e. ZipUtility.unzipFiles("/srcDir", "myZipFile.zip", "/destination");
Andrew Dyster
@eirikma: I think the libraries focus on giving you the general tools and your app has to adapt them to your situation. Apache is specialist in making utility classes (providing packed classes-methods to implement a common scenario use of the libraries). I don't know about any zip utility (one that provides what you want). But in general I'd program one, save it someplace as a library and use it. If I later discover that there's an accepted utility I can change the app code or even my ad-hoc utility class to use it.
helios
A: 

It seems like it's possible to do what I want using the TrueZip library: https://truezip.dev.java.net/manual-6.html#Copying

This is not an ideal situation, since the library is quite large and with a larger scope than I need (and also with some peculiar and confusing details such as being organized around subclasses of java.io.File which are also called File for use in classes that typically also handles java.io.File instances!).

At least I don't have to be in a situation where a majority of the code lines in the class are unrelated to the responsibility of the class, or to maintain a complex utility class in the project that is unrelated to the purpose of the module.

I think this is a typical example on the main reason why experienced developers are migrating from Java to Ruby. Despite an abundance of libraries in java, too many of them are poorly designed so that simple operations become just as difficult to perform as the more specialized ones. Seems like they are written from the bottom up by technology experts more eager to expose all details and possibilities than to make everyday tasks simple. The apache commons people deserves honor for creating libraries that relieve your class from code lines, especially loops and conditionals, that are unrelated to the business purpose of the class.

eirikma
hmm. doesn't work exactly as I expected. it recurses into the jar files inside the zip and extracts them too despite me using code the manual says won't do that. Not what I had in mind.
eirikma