com.nsftools.zip
Class ZipFileManager

java.lang.Object
  extended by com.nsftools.zip.ZipFileManager

public class ZipFileManager
extends java.lang.Object

ZipFileManager is a Java class that is meant to simplify the process of reading from, creating, and modifying zip files.

Here's some example code of the class in action:

// if this file doesn't exist, it will be created; otherwise, the existing file can be
// read and updated
ZipFileManager zipFile = new ZipFileManager("c:\\test.zip");

// optionally redirect debug messages to System.out, in case we want to
// read them
zipFile.setDebugStream(System.out);

// optionally set a relative path, so any files we add that are beneath this
// subdirectory will have the relative directory information stripped off
// (for example, if the relative path is "c:\\temp" and the file is at "c:\\temp\\foo.txt"
// it will be added as "foo.txt" instead of "temp\\foo.txt"; if the file is at "c:\\a1\\foo.txt"
// the relative path will be ignored and it will be added as "a1\\foo.txt")
zipFile.setRelativePath("c:\\temp");

// if an entry with a label of "foo.txt" already exists in the file, remove it (an array
// of the existing entries, if any, can be retrieved with a call to getEntryNames)
zipFile.removeEntry("foo.txt");

// add the file at "c:\\test.txt" to the zip file
zipFile.addEntry("c:\\test.txt");

// add the file at "c:\\test2.txt" only if the file on disc is newer than the existing file
// in the zip file (or if the file is not yet in the zip file)
zipFile.updateEntry("c:\\test2.txt");

// add all files in the directory "c:\\temp\\a1" to the zip file, including subdirectories
zipFile.addDirectoryEntry("c:\\temp\\a1");

// update the contents of (or create) the zip file with your changes and close it
// (you could also have called the processChanges method to update the
// file and continue modifying it)
zipFile.close();

version 1.0
December 26, 2005
Copyright 2005 Julian Robichaux -- http://www.nsftools.com

Licensed under the Academic Free License version 2.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://opensource.org/licenses/afl-2.1.php

Version:
1.0
Author:
Julian Robichaux -- http://www.nsftools.com

Constructor Summary
ZipFileManager(java.io.File zipFile)
          Create a new ZipFileManager object, using the given zipFile as the file we'll be reading from and potentially updating.
ZipFileManager(java.lang.String zipFileName)
          Same as the other constructor, but allows a file name String instead of a File object.
 
Method Summary
 void addDirectoryEntry(java.io.File dir)
          Add all files in the specified directory to the new zip file, including all subdirectories.
 void addDirectoryEntry(java.io.File dir, int howDeep)
          Add all files in the specified directory to the new zip file.
 void addDirectoryEntry(java.io.File dir, int howDeep, java.io.FileFilter filter)
          Add all files in the specified directory to the new zip file.
 void addDirectoryEntry(java.lang.String dirName)
          Add all files in the specified directory to the new zip file, including all subdirectories.
 void addDirectoryEntry(java.lang.String dirName, int howDeep)
          Add all files in the specified directory to the new zip file.
 void addEntry(java.io.File file)
          Add the specified file to the new zip file.
 void addEntry(java.lang.String fileName)
          Add the specified file to the new zip file.
 void addEntry(java.lang.String fileName, java.lang.String comment)
          Add the specified file to the new zip file, with the specified comment.
 boolean areChangesPending()
          Returns true if there are changes pending (adds, removes, or updates) since the last time processChanges was called.
 void close()
          Write any outstanding changes (adds, removes, or updates) to the zip file (if any) and close the internal reference to the zip file.
 void close(boolean doProcessChanges)
          Close the internal reference to the zip file.
 java.lang.String getCurrentZipFileName()
          Return the name of the zip file we're currently working with, if any.
 java.util.Hashtable getEntries()
          Return the list of entries that are currently in the zip file (not including any files you've added since the last call to processChanges).
 java.util.zip.ZipEntry getEntry(java.lang.String entryName)
          Return the ZipEntry associated with the given entryName, if any
 java.lang.String[] getEntryNames()
          Return a String array of the entry names that are currently in the zip file (not including any files you've added since the last call to processChanges)
 java.io.InputStream getEntryStream(java.lang.String entryName)
          Get the given entry as an InputStream, if it currently exists in the zip file.
 java.lang.String[] getNewEntryNames()
          Return a String array of the files that will be added to the zip file (this list is reset every time you make a call to processChanges)
 java.lang.String[] getNewFilesAdded()
          Return a String array of the new files that have already been added to the zip file as a result to ALL previous calls to processChanges (not including any files you've added since the last call to processChanges)
 java.lang.String getNewZipFileName()
          Return the name of the zip file that will be created when processChanges or close is called.
 java.lang.String getRelativePath()
          Get the current relative path assignment that is in effect.
 java.lang.String processChanges()
          Same as the other version of processChanges, with ignoreErrors set to false (which means the process will fail with an Exception if there are I/O errors reading or writing files).
 java.lang.String processChanges(boolean ignoreErrors)
          Process all outstanding changes to the zip file.
 void removeEntry(java.lang.String entryName)
          Remove the specified entry from the current zip file, if it exists.
 void saveEntryAsFile(java.lang.String entryName, java.lang.String newFileName)
          If the given entryName is found in the current zip file, decompress it and save it on disc to the given newFileName.
 void setDebugStream(java.io.OutputStream out)
          If you want the debug messages to be piped to an OutputStream, set it here
 void setNewZipFileName(java.lang.String newFileName)
          Change the name of the zip file we will output our changes to.
 void setRelativePath(java.lang.String pathName)
          Set the relative path for files that are added to this zip file.
 void updateDirectoryEntry(java.io.File dir)
          Same as addDirectoryEntry, only it uses the logic in the updateEntry method for each file instead of the logic in addEntry.
 void updateDirectoryEntry(java.io.File dir, int howDeep)
          Same as addDirectoryEntry, only it uses the logic in the updateEntry method for each file instead of the logic in addEntry.
 void updateDirectoryEntry(java.io.File dir, int howDeep, java.io.FileFilter filter)
          Same as addDirectoryEntry, only it uses the logic in the updateEntry method for each file instead of the logic in addEntry.
 void updateDirectoryEntry(java.lang.String dirName)
          Same as addDirectoryEntry, only it uses the logic in the updateEntry method for each file instead of the logic in addEntry.
 void updateDirectoryEntry(java.lang.String dirName, int howDeep)
          Same as addDirectoryEntry, only it uses the logic in the updateEntry method for each file instead of the logic in addEntry.
 void updateEntry(java.io.File file)
          If this file already exists in the zip file (based on the relative path name of the file) and the version on disc is newer than the version in the zip file, replace the version in the zip file with the one on disc.
 void updateEntry(java.lang.String fileName)
          Same as the other updateEntry method, only you can use a fileName String instead of a File object.
 void updateEntry(java.lang.String entryName, java.io.File file)
          Compare the given entry to the given file, and if the file on disc is newer than the entry in the zip file, replace the entry with the file.
 void updateEntry(java.lang.String entryName, java.lang.String fileName)
          Same as the other updateEntry method, only you can use a fileName String instead of a File object.
 
Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

ZipFileManager

public ZipFileManager(java.io.File zipFile)
               throws java.io.IOException
Create a new ZipFileManager object, using the given zipFile as the file we'll be reading from and potentially updating. If the given file does not yet exist (i.e. you want to add entries to a new file), it will be created when you call processChanges or close. If the file exists and it's not a valid java.util.zip.ZipFile, you will get a ZipException and your new ZipFileManager object will not be instantiated.

Throws:
java.io.IOException

ZipFileManager

public ZipFileManager(java.lang.String zipFileName)
               throws java.io.IOException
Same as the other constructor, but allows a file name String instead of a File object.

Throws:
java.io.IOException
Method Detail

setDebugStream

public void setDebugStream(java.io.OutputStream out)
If you want the debug messages to be piped to an OutputStream, set it here


getEntries

public java.util.Hashtable getEntries()
Return the list of entries that are currently in the zip file (not including any files you've added since the last call to processChanges). This list is a Hashtable, with the entry name as the key (essentially a relative file name), and a ZipEntry object as the element.


getEntry

public java.util.zip.ZipEntry getEntry(java.lang.String entryName)
Return the ZipEntry associated with the given entryName, if any


getEntryNames

public java.lang.String[] getEntryNames()
Return a String array of the entry names that are currently in the zip file (not including any files you've added since the last call to processChanges)


getNewEntryNames

public java.lang.String[] getNewEntryNames()
Return a String array of the files that will be added to the zip file (this list is reset every time you make a call to processChanges)


getNewFilesAdded

public java.lang.String[] getNewFilesAdded()
Return a String array of the new files that have already been added to the zip file as a result to ALL previous calls to processChanges (not including any files you've added since the last call to processChanges)


getEntryStream

public java.io.InputStream getEntryStream(java.lang.String entryName)
                                   throws java.io.IOException
Get the given entry as an InputStream, if it currently exists in the zip file. To get the list of entries that are currently in the zip file, use getEntryNames.

Throws:
java.io.IOException

saveEntryAsFile

public void saveEntryAsFile(java.lang.String entryName,
                            java.lang.String newFileName)
                     throws java.io.IOException
If the given entryName is found in the current zip file, decompress it and save it on disc to the given newFileName. The entry will NOT be removed from the zip file after it's saved to disc.

Throws:
java.io.IOException

removeEntry

public void removeEntry(java.lang.String entryName)
Remove the specified entry from the current zip file, if it exists. The change will NOT take effect until you call processChanges or close.


setRelativePath

public void setRelativePath(java.lang.String pathName)
Set the relative path for files that are added to this zip file. For example, if you set the relative path as "c:\temp" and you add a file at "c:\temp\foo.txt", it will be added as "foo.txt". If no relative path has been set (or the relative path is to a different directory), the file would be added as "temp\foo.txt". The relative path can be changed multiple times -- as new files are added, the most recent relative path assignment will be applied.


getRelativePath

public java.lang.String getRelativePath()
Get the current relative path assignment that is in effect.


addEntry

public void addEntry(java.lang.String fileName,
                     java.lang.String comment)
              throws java.lang.IllegalArgumentException
Add the specified file to the new zip file, with the specified comment. The change will NOT take effect until you call processChanges or close. The maximum length of a comment is 0xFFFF (65,535) bytes, so any comment string longer than that will be truncated accordingly. This should not normally be an issue.

Throws:
java.lang.IllegalArgumentException

addEntry

public void addEntry(java.lang.String fileName)
              throws java.lang.IllegalArgumentException
Add the specified file to the new zip file. The change will NOT take effect until you call processChanges or close.

Throws:
java.lang.IllegalArgumentException

addEntry

public void addEntry(java.io.File file)
              throws java.lang.IllegalArgumentException,
                     java.io.IOException
Add the specified file to the new zip file. The change will NOT take effect until you call processChanges or close.

Throws:
java.lang.IllegalArgumentException
java.io.IOException

addDirectoryEntry

public void addDirectoryEntry(java.lang.String dirName)
                       throws java.lang.IllegalArgumentException,
                              java.io.IOException
Add all files in the specified directory to the new zip file, including all subdirectories. The change will NOT take effect until you call processChanges or close.

Throws:
java.lang.IllegalArgumentException
java.io.IOException

addDirectoryEntry

public void addDirectoryEntry(java.io.File dir)
                       throws java.lang.IllegalArgumentException,
                              java.io.IOException
Add all files in the specified directory to the new zip file, including all subdirectories. The change will NOT take effect until you call processChanges or close.

Throws:
java.lang.IllegalArgumentException
java.io.IOException

addDirectoryEntry

public void addDirectoryEntry(java.lang.String dirName,
                              int howDeep)
                       throws java.lang.IllegalArgumentException,
                              java.io.IOException
Add all files in the specified directory to the new zip file. The howDeep parameter determines how many levels of subdirectories we should traverse. Some examples: If howDeep = 0, no subdirectories will be added (only the files at the root of the base directory are added) If howDeep = 1, the first level of subdirectories will be added If howDeep = -1, all subdirectories will be added. The change will NOT take effect until you call processChanges or close.

Throws:
java.lang.IllegalArgumentException
java.io.IOException

addDirectoryEntry

public void addDirectoryEntry(java.io.File dir,
                              int howDeep)
                       throws java.lang.IllegalArgumentException,
                              java.io.IOException
Add all files in the specified directory to the new zip file. The howDeep parameter determines how many levels of subdirectories we should traverse. Some examples: If howDeep = 0, no subdirectories will be added (only the files at the root of the base directory are added) If howDeep = 1, the first level of subdirectories will be added If howDeep = -1, all subdirectories will be added. The change will NOT take effect until you call processChanges or close.

Throws:
java.lang.IllegalArgumentException
java.io.IOException

addDirectoryEntry

public void addDirectoryEntry(java.io.File dir,
                              int howDeep,
                              java.io.FileFilter filter)
                       throws java.lang.IllegalArgumentException,
                              java.io.IOException
Add all files in the specified directory to the new zip file. The howDeep parameter determines how many levels of subdirectories we should traverse. Some examples: If howDeep = 0, no subdirectories will be added (only the files at the root of the base directory are added) If howDeep = 1, the first level of subdirectories will be added If howDeep = -1, all subdirectories will be added. A FileFilter can also be specified, to limit the files that are added to a certain subset of files (like only .log files, or everything but .sys files, or something similar). The change will NOT take effect until you call processChanges or close.

Throws:
java.lang.IllegalArgumentException
java.io.IOException

updateEntry

public void updateEntry(java.lang.String entryName,
                        java.io.File file)
                 throws java.io.IOException
Compare the given entry to the given file, and if the file on disc is newer than the entry in the zip file, replace the entry with the file. If the entry does not already exist in the zip file, the file will just be added. If it exists but the last modified time is the same as or after the modified time of the file on disc, nothing will be changed. The change will NOT take effect until you call processChanges or close.

Throws:
java.io.IOException

updateEntry

public void updateEntry(java.lang.String entryName,
                        java.lang.String fileName)
                 throws java.io.IOException
Same as the other updateEntry method, only you can use a fileName String instead of a File object.

Throws:
java.io.IOException

updateEntry

public void updateEntry(java.io.File file)
                 throws java.io.IOException
If this file already exists in the zip file (based on the relative path name of the file) and the version on disc is newer than the version in the zip file, replace the version in the zip file with the one on disc. If the file does not already exist in the zip file (based on relative path) or the version in the zip file was modified at the same time or after the version on disc, nothing will happen. The change will NOT take effect until you call processChanges or close.

Throws:
java.io.IOException

updateEntry

public void updateEntry(java.lang.String fileName)
                 throws java.io.IOException
Same as the other updateEntry method, only you can use a fileName String instead of a File object.

Throws:
java.io.IOException

updateDirectoryEntry

public void updateDirectoryEntry(java.lang.String dirName)
                          throws java.lang.IllegalArgumentException,
                                 java.io.IOException
Same as addDirectoryEntry, only it uses the logic in the updateEntry method for each file instead of the logic in addEntry.

Throws:
java.lang.IllegalArgumentException
java.io.IOException

updateDirectoryEntry

public void updateDirectoryEntry(java.io.File dir)
                          throws java.lang.IllegalArgumentException,
                                 java.io.IOException
Same as addDirectoryEntry, only it uses the logic in the updateEntry method for each file instead of the logic in addEntry.

Throws:
java.lang.IllegalArgumentException
java.io.IOException

updateDirectoryEntry

public void updateDirectoryEntry(java.lang.String dirName,
                                 int howDeep)
                          throws java.lang.IllegalArgumentException,
                                 java.io.IOException
Same as addDirectoryEntry, only it uses the logic in the updateEntry method for each file instead of the logic in addEntry.

Throws:
java.lang.IllegalArgumentException
java.io.IOException

updateDirectoryEntry

public void updateDirectoryEntry(java.io.File dir,
                                 int howDeep)
                          throws java.lang.IllegalArgumentException,
                                 java.io.IOException
Same as addDirectoryEntry, only it uses the logic in the updateEntry method for each file instead of the logic in addEntry.

Throws:
java.lang.IllegalArgumentException
java.io.IOException

updateDirectoryEntry

public void updateDirectoryEntry(java.io.File dir,
                                 int howDeep,
                                 java.io.FileFilter filter)
                          throws java.lang.IllegalArgumentException,
                                 java.io.IOException
Same as addDirectoryEntry, only it uses the logic in the updateEntry method for each file instead of the logic in addEntry.

Throws:
java.lang.IllegalArgumentException
java.io.IOException

getCurrentZipFileName

public java.lang.String getCurrentZipFileName()
Return the name of the zip file we're currently working with, if any. If it's a new file that will be created when processChanges is called, this will return an empty String (""); however, you could get the name that the new file will be called with the getNewZipFileName method. If you've already made a call to processChanges and this value is NOT the same as getNewZipFileName, that likely means that there was an error renaming the temp file. In that case, this will be the name of the temp file that was created as the zip file was being created.


getNewZipFileName

public java.lang.String getNewZipFileName()
Return the name of the zip file that will be created when processChanges or close is called. By default, this is the same as the name of the file that was specified when this ZipFileManager object was created, which means any original file will be overwritten.


setNewZipFileName

public void setNewZipFileName(java.lang.String newFileName)
Change the name of the zip file we will output our changes to. By default, we overwrite the file that was specified when this ZipFileManager object was created. However, you may want to leave the original file intact and make a brand new file based on the original file, in which case you would specify a new name here. If the file name you specify is invalid, no error will occur until you call processChanges or close, at which time the zip file will be created, but it will be in a temporary file instead of the file name you want.


processChanges

public java.lang.String processChanges()
                                throws java.io.IOException
Same as the other version of processChanges, with ignoreErrors set to false (which means the process will fail with an Exception if there are I/O errors reading or writing files).

Throws:
java.io.IOException

processChanges

public java.lang.String processChanges(boolean ignoreErrors)
                                throws java.io.IOException
Process all outstanding changes to the zip file. This includes removing entries, adding or updating existing entries, or creating the new zip file (if the file does not yet exist, or if the newZipFileName is different from the current zip file name). With a zip file in Java, you can't make updates to an existing zip file in-place, so what you have to do is copy all the old entries you want to keep into a new file, add any new entries to that file, close the file stream and copy the new file over the old one. Normally this is pretty fast, but it obviously slows down as the files increase in size and/or number. The ignoreErrors parameter indicates whether IO errors that occur as we're writing to the new zip file should be ignored or not. Errors could happen if a filename is incorrect, or the user doesn't have access to open the file, for example. If ignoreErrors is true, the errors will be ignored and the new zip file will be created without the files that caused errors (error messages will show up on the debug stream, if you're interested). If ignoreErrors is false, the entire process will throw an IOException at the first error and the new zip file will NOT be created. If this method completes successfully, the return value will be the file name and path of the zip file that was created. This will either be the value of the newZipFileName variable (which is, by default, the name of the zip file that was specified when this ZipFileManager object was created), or if there was an error writing to the location specified by newZipFileName (often an error regarding write or delete permissions), the name of the temporary file that contains the new zip file contents.

Throws:
java.io.IOException

areChangesPending

public boolean areChangesPending()
Returns true if there are changes pending (adds, removes, or updates) since the last time processChanges was called.


close

public void close()
           throws java.io.IOException
Write any outstanding changes (adds, removes, or updates) to the zip file (if any) and close the internal reference to the zip file.

Throws:
java.io.IOException

close

public void close(boolean doProcessChanges)
           throws java.io.IOException
Close the internal reference to the zip file. If doProcessChanges is true and there are outstanding changes to be made (adds, removes, or updates), the processChanges method will be called first.

Throws:
java.io.IOException