commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Peter Henderson <peter.hender...@starjar.com>
Subject [IO] Suggestion add ZipUtils class
Date Tue, 22 Jul 2008 10:08:35 GMT
Hi folks.

I've recently been working with zip files and saw that commons IO did not support them.

May I suggest that a ZipUtils class is added to commons IO, perhaps with my meagre contribution
which has one simple function: expand a zip file from an input stream to a directory. (and
a support
function which could go into IOUtils)


Cheers

Peter Henderson.




/*
 * ZipUtils.java
 *
 * Created on 22-Jul-2008
 */
package org.apache.commons.io;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * Utility classes to simplify working with zip files and streams.
 *
 * @author peter
 */
public class ZipUtils {

    /**
     * Copy the contents of a zip stream to a directory.
     * Can be used to copy resource streams within the applications jar to
     * disk.
     * The directory structure in the zip file is maintained.
     *
     * Example usage
     * <pre>
     *      InputStream is = this.getClass().getResourceAsStream("/res/test.zip");
     *      ZipUtils.expandZip(is, new File("/tmp"));
     * </pre>
     *
     *
     * @param is input stream reading a zip file
     * @param dir the directory to expand the content of the zip into. The
     * directory is created if it does not already exist
     * @throws java.io.IOException
     *   if the directory could not be created,
     *   an entry could not be loaded from the stream,
     *   an output stream could not be opened,
     *   an zip entry contents could not be read
     */
    public static void expandZip(InputStream is, File dir) throws IOException {

        if (!dir.exists()) {
            FileUtils.forceMkdir(dir);
        }

        ZipInputStream zipIS = new ZipInputStream(is);
        ZipEntry entry = zipIS.getNextEntry();
        while (entry != null) {

            //System.out.format("Entry %s\n", entry.getName());

            File f = new File(dir, entry.getName());
            if (entry.isDirectory()) {
                f.mkdir();
            } else {
                FileOutputStream fileOS = FileUtils.openOutputStream(f);

                // @TODO move copy with length funtion in to IOUtils.
                copy(zipIS, fileOS, entry.getSize());

                fileOS.close();
            }

            entry = zipIS.getNextEntry();
        }

    }

    //
    // TODO add this to IOUtils
    //
    /**
     * The default buffer size to use.
     */
    private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;


    /**
     * Copy <code>length</code> bytes from an <code>InputStream</code>
to an
     * <code>OutputStream</code>.
     * <p>
     * This method buffers the input internally, so there is no need to use a
     * <code>BufferedInputStream</code>.
     *
     * @param input the <code>InputStream</code> to read from
     * @param output the <code>OutputStream</code> to write to
     * @param length the number of bytes to copy
     * @throws NullPointerException if the input or output is null
     * @throws IllegalArgumentException if length is negative
     * @throws IOException if the input stream does not contain enough data to
     * copy or an I/O error occurs
     * @since Commons IO 1.4
     */
    public static void copy(InputStream input, OutputStream output, long length)
            throws IOException {
        if (length < 0) {
            throw new IllegalArgumentException("Length is less than " +
                    "zero, cannot copy a negative number of bytes?");
        }
        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];

        long written = 0;
        while (written != length) {
            long outstanding = length - written;
            int toRead;
            if (outstanding > buffer.length) {
                toRead = buffer.length;
            } else {
                toRead = (int) outstanding;
            }

            int read = input.read(buffer, 0, toRead);
            if (read == -1) {
                throw new IOException(
                        "Input stream does not contain enough data");
            }
            output.write(buffer, 0, read);

            written += read;
        }
    }
}


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org


Mime
View raw message