org.apache.commons.compress.archivers.zip
Class ZipArchiveOutputStream

java.lang.Object
  extended by java.io.OutputStream
      extended by org.apache.commons.compress.archivers.ArchiveOutputStream
          extended by org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream
All Implemented Interfaces:
java.io.Closeable, java.io.Flushable
Direct Known Subclasses:
JarArchiveOutputStream

public class ZipArchiveOutputStream
extends ArchiveOutputStream

Reimplementation of java.util.zip.ZipOutputStream that does handle the extended functionality of this package, especially internal/external file attributes and extra fields with different layouts for local file data and central directory entries.

This class will try to use RandomAccessFile when you know that the output is going to go to a file.

If RandomAccessFile cannot be used, this implementation will use a Data Descriptor to store size and CRC information for DEFLATED entries, this means, you don't need to calculate them yourself. Unfortunately this is not possible for the STORED method, here setting the CRC and uncompressed size information is required before putArchiveEntry(ArchiveEntry) can be called.


Nested Class Summary
static class ZipArchiveOutputStream.UnicodeExtraFieldPolicy
          enum that represents the possible policies for creating Unicode extra fields.
 
Field Summary
private  byte[] buf
          This buffer servers as a Deflater.
(package private) static int BUFFER_SIZE
           
(package private) static int BYTE_MASK
           
private  long cdLength
          Length of central directory.
private  long cdOffset
          Start of central directory.
(package private) static byte[] CFH_SIG
          central file header signature
private  java.lang.String comment
          The file comment.
private  java.util.zip.CRC32 crc
          CRC instance to avoid parsing DEFLATED data twice.
private  ZipArchiveOutputStream.UnicodeExtraFieldPolicy createUnicodeExtraFields
          whether to create UnicodePathExtraField-s for each entry.
private  long dataStart
          Data for local header data
(package private) static byte[] DD_SIG
          data descriptor signature
protected  java.util.zip.Deflater def
          This Deflater object is used for output.
static int DEFAULT_COMPRESSION
          Default compression level for deflated entries.
(package private) static java.lang.String DEFAULT_ENCODING
          default encoding for file names and comment.
static int DEFLATED
          Compression method for deflated entries.
private static int DEFLATER_BLOCK_SIZE
           
static int EFS_FLAG
          Deprecated. use GeneralPurposeBit.UFT8_NAMES_FLAG instead
private  java.lang.String encoding
          The encoding to use for filenames and the file comment.
private  java.util.List entries
          List of ZipArchiveEntries written so far.
private  ZipArchiveEntry entry
          Current entry.
(package private) static byte[] EOCD_SIG
          end of central dir signature
private  boolean fallbackToUTF8
          Whether to encode non-encodable file names as UTF-8.
protected  boolean finished
          indicates if this archive is finished.
private  boolean hasCompressionLevelChanged
          Has the compression level changed when compared to the last entry?
private  int level
          Compression level for next entry.
(package private) static byte[] LFH_SIG
          local file header signature
private  long localDataStart
          Offset for CRC entry in the local file header data for the current entry starts here.
private static byte[] LZERO
          Helper, a 0 as ZipLong.
private  int method
          Default compression method for next entry.
private  java.util.Map offsets
          Holds the offsets of the LFH starts for each entry.
private  java.io.OutputStream out
           
private  java.io.RandomAccessFile raf
          Optional random access output.
private static int SHORT
           
static int STORED
          Compression method for stored entries.
private  boolean useUTF8Flag
          whether to use the general purpose bit flag when writing UTF-8 filenames or not.
private static int WORD
           
private  long written
          Count the bytes written to out.
private static byte[] ZERO
          Helper, a 0 as ZipShort.
private  ZipEncoding zipEncoding
          The zip encoding to use for filenames and the file comment.
 
Constructor Summary
ZipArchiveOutputStream(java.io.File file)
          Creates a new ZIP OutputStream writing to a File.
ZipArchiveOutputStream(java.io.OutputStream out)
          Creates a new ZIP OutputStream filtering the underlying stream.
 
Method Summary
 boolean canWriteEntryData(ArchiveEntry ae)
          Whether this stream is able to write the given entry.
 void close()
          Closes this output stream and releases any system resources associated with the stream.
 void closeArchiveEntry()
          Writes all necessary data for this entry.
 ArchiveEntry createArchiveEntry(java.io.File inputFile, java.lang.String entryName)
          Creates a new zip entry taking some information from the given file and using the provided name.
protected  void deflate()
          Writes next block of compressed data to the output stream.
private  void deflateUntilInputIsNeeded()
           
 void finish()
          Finishes the addition of entries to this stream, without closing it.
 void flush()
          Flushes this output stream and forces any buffered output bytes to be written out to the stream.
 java.lang.String getEncoding()
          The encoding to use for filenames and the file comment.
 boolean isSeekable()
          This method indicates whether this archive is writing to a seekable stream (i.e., to a random access file).
 void putArchiveEntry(ArchiveEntry archiveEntry)
          Writes the headers for an archive entry to the output stream.
 void setComment(java.lang.String comment)
          Set the file comment.
 void setCreateUnicodeExtraFields(ZipArchiveOutputStream.UnicodeExtraFieldPolicy b)
          Whether to create Unicode Extra Fields.
 void setEncoding(java.lang.String encoding)
          The encoding to use for filenames and the file comment.
 void setFallbackToUTF8(boolean b)
          Whether to fall back to UTF and the language encoding flag if the file name cannot be encoded using the specified encoding.
 void setLevel(int level)
          Sets the compression level for subsequent entries.
 void setMethod(int method)
          Sets the default compression method for subsequent entries.
 void setUseLanguageEncodingFlag(boolean b)
          Whether to set the language encoding flag if the file name encoding is UTF-8.
 void write(byte[] b, int offset, int length)
          Writes bytes to ZIP entry.
protected  void writeCentralDirectoryEnd()
          Writes the "End of central dir record".
protected  void writeCentralFileHeader(ZipArchiveEntry ze)
          Writes the central file header entry.
protected  void writeDataDescriptor(ZipArchiveEntry ze)
          Writes the data descriptor entry.
protected  void writeLocalFileHeader(ZipArchiveEntry ze)
          Writes the local file header entry
protected  void writeOut(byte[] data)
          Write bytes to output or random access file.
protected  void writeOut(byte[] data, int offset, int length)
          Write bytes to output or random access file.
private  void writeVersionNeededToExtractAndGeneralPurposeBits(int zipMethod, boolean utfFallback)
           
 
Methods inherited from class org.apache.commons.compress.archivers.ArchiveOutputStream
count, count, getBytesWritten, getCount, write
 
Methods inherited from class java.io.OutputStream
write
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

BYTE_MASK

static final int BYTE_MASK
See Also:
Constant Field Values

SHORT

private static final int SHORT
See Also:
Constant Field Values

WORD

private static final int WORD
See Also:
Constant Field Values

BUFFER_SIZE

static final int BUFFER_SIZE
See Also:
Constant Field Values

finished

protected boolean finished
indicates if this archive is finished. protected for use in Jar implementation


DEFLATER_BLOCK_SIZE

private static final int DEFLATER_BLOCK_SIZE
See Also:
Constant Field Values

DEFLATED

public static final int DEFLATED
Compression method for deflated entries.

See Also:
Constant Field Values

DEFAULT_COMPRESSION

public static final int DEFAULT_COMPRESSION
Default compression level for deflated entries.

See Also:
Constant Field Values

STORED

public static final int STORED
Compression method for stored entries.

See Also:
Constant Field Values

DEFAULT_ENCODING

static final java.lang.String DEFAULT_ENCODING
default encoding for file names and comment.

See Also:
Constant Field Values

EFS_FLAG

public static final int EFS_FLAG
Deprecated. use GeneralPurposeBit.UFT8_NAMES_FLAG instead
General purpose flag, which indicates that filenames are written in utf-8.

See Also:
Constant Field Values

entry

private ZipArchiveEntry entry
Current entry.


comment

private java.lang.String comment
The file comment.


level

private int level
Compression level for next entry.


hasCompressionLevelChanged

private boolean hasCompressionLevelChanged
Has the compression level changed when compared to the last entry?


method

private int method
Default compression method for next entry.


entries

private final java.util.List entries
List of ZipArchiveEntries written so far.


crc

private final java.util.zip.CRC32 crc
CRC instance to avoid parsing DEFLATED data twice.


written

private long written
Count the bytes written to out.


dataStart

private long dataStart
Data for local header data


localDataStart

private long localDataStart
Offset for CRC entry in the local file header data for the current entry starts here.


cdOffset

private long cdOffset
Start of central directory.


cdLength

private long cdLength
Length of central directory.


ZERO

private static final byte[] ZERO
Helper, a 0 as ZipShort.


LZERO

private static final byte[] LZERO
Helper, a 0 as ZipLong.


offsets

private final java.util.Map offsets
Holds the offsets of the LFH starts for each entry.


encoding

private java.lang.String encoding
The encoding to use for filenames and the file comment.

For a list of possible values see http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html. Defaults to UTF-8.


zipEncoding

private ZipEncoding zipEncoding
The zip encoding to use for filenames and the file comment. This field is of internal use and will be set in setEncoding(String).


def

protected final java.util.zip.Deflater def
This Deflater object is used for output.


buf

private final byte[] buf
This buffer servers as a Deflater.


raf

private final java.io.RandomAccessFile raf
Optional random access output.


out

private final java.io.OutputStream out

useUTF8Flag

private boolean useUTF8Flag
whether to use the general purpose bit flag when writing UTF-8 filenames or not.


fallbackToUTF8

private boolean fallbackToUTF8
Whether to encode non-encodable file names as UTF-8.


createUnicodeExtraFields

private ZipArchiveOutputStream.UnicodeExtraFieldPolicy createUnicodeExtraFields
whether to create UnicodePathExtraField-s for each entry.


LFH_SIG

static final byte[] LFH_SIG
local file header signature


DD_SIG

static final byte[] DD_SIG
data descriptor signature


CFH_SIG

static final byte[] CFH_SIG
central file header signature


EOCD_SIG

static final byte[] EOCD_SIG
end of central dir signature

Constructor Detail

ZipArchiveOutputStream

public ZipArchiveOutputStream(java.io.OutputStream out)
Creates a new ZIP OutputStream filtering the underlying stream.

Parameters:
out - the outputstream to zip

ZipArchiveOutputStream

public ZipArchiveOutputStream(java.io.File file)
                       throws java.io.IOException
Creates a new ZIP OutputStream writing to a File. Will use random access if possible.

Parameters:
file - the file to zip to
Throws:
java.io.IOException - on error
Method Detail

isSeekable

public boolean isSeekable()
This method indicates whether this archive is writing to a seekable stream (i.e., to a random access file).

For seekable streams, you don't need to calculate the CRC or uncompressed size for STORED entries before invoking putArchiveEntry(ArchiveEntry).

Returns:
true if seekable

setEncoding

public void setEncoding(java.lang.String encoding)
The encoding to use for filenames and the file comment.

For a list of possible values see http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html. Defaults to UTF-8.

Parameters:
encoding - the encoding to use for file names, use null for the platform's default encoding

getEncoding

public java.lang.String getEncoding()
The encoding to use for filenames and the file comment.

Returns:
null if using the platform's default character encoding.

setUseLanguageEncodingFlag

public void setUseLanguageEncodingFlag(boolean b)
Whether to set the language encoding flag if the file name encoding is UTF-8.

Defaults to true.


setCreateUnicodeExtraFields

public void setCreateUnicodeExtraFields(ZipArchiveOutputStream.UnicodeExtraFieldPolicy b)
Whether to create Unicode Extra Fields.

Defaults to NEVER.


setFallbackToUTF8

public void setFallbackToUTF8(boolean b)
Whether to fall back to UTF and the language encoding flag if the file name cannot be encoded using the specified encoding.

Defaults to false.


finish

public void finish()
            throws java.io.IOException
Finishes the addition of entries to this stream, without closing it. Additional data can be written, if the format supports it. The finish() method throws an Exception if the user forgets to close the entry .

Specified by:
finish in class ArchiveOutputStream
Throws:
java.io.IOException

closeArchiveEntry

public void closeArchiveEntry()
                       throws java.io.IOException
Writes all necessary data for this entry.

Specified by:
closeArchiveEntry in class ArchiveOutputStream
Throws:
java.io.IOException - on error

putArchiveEntry

public void putArchiveEntry(ArchiveEntry archiveEntry)
                     throws java.io.IOException
Writes the headers for an archive entry to the output stream. The caller must then write the content to the stream and call ArchiveOutputStream.closeArchiveEntry() to complete the process.

Specified by:
putArchiveEntry in class ArchiveOutputStream
Parameters:
archiveEntry - describes the entry
Throws:
java.lang.ClassCastException - if entry is not an instance of ZipArchiveEntry
java.io.IOException

setComment

public void setComment(java.lang.String comment)
Set the file comment.

Parameters:
comment - the comment

setLevel

public void setLevel(int level)
Sets the compression level for subsequent entries.

Default is Deflater.DEFAULT_COMPRESSION.

Parameters:
level - the compression level.
Throws:
java.lang.IllegalArgumentException - if an invalid compression level is specified.

setMethod

public void setMethod(int method)
Sets the default compression method for subsequent entries.

Default is DEFLATED.

Parameters:
method - an int from java.util.zip.ZipEntry

canWriteEntryData

public boolean canWriteEntryData(ArchiveEntry ae)
Whether this stream is able to write the given entry.

May return false if it is set up to use encryption or a compression method that hasn't been implemented yet.

Overrides:
canWriteEntryData in class ArchiveOutputStream
Since:
Apache Commons Compress 1.1

write

public void write(byte[] b,
                  int offset,
                  int length)
           throws java.io.IOException
Writes bytes to ZIP entry.

Overrides:
write in class java.io.OutputStream
Parameters:
b - the byte array to write
offset - the start position to write from
length - the number of bytes to write
Throws:
java.io.IOException - on error

close

public void close()
           throws java.io.IOException
Closes this output stream and releases any system resources associated with the stream.

Specified by:
close in interface java.io.Closeable
Overrides:
close in class java.io.OutputStream
Throws:
java.io.IOException - if an I/O error occurs.

flush

public void flush()
           throws java.io.IOException
Flushes this output stream and forces any buffered output bytes to be written out to the stream.

Specified by:
flush in interface java.io.Flushable
Overrides:
flush in class java.io.OutputStream
Throws:
java.io.IOException - if an I/O error occurs.

deflate

protected final void deflate()
                      throws java.io.IOException
Writes next block of compressed data to the output stream.

Throws:
java.io.IOException - on error

writeLocalFileHeader

protected void writeLocalFileHeader(ZipArchiveEntry ze)
                             throws java.io.IOException
Writes the local file header entry

Parameters:
ze - the entry to write
Throws:
java.io.IOException - on error

writeDataDescriptor

protected void writeDataDescriptor(ZipArchiveEntry ze)
                            throws java.io.IOException
Writes the data descriptor entry.

Parameters:
ze - the entry to write
Throws:
java.io.IOException - on error

writeCentralFileHeader

protected void writeCentralFileHeader(ZipArchiveEntry ze)
                               throws java.io.IOException
Writes the central file header entry.

Parameters:
ze - the entry to write
Throws:
java.io.IOException - on error

writeCentralDirectoryEnd

protected void writeCentralDirectoryEnd()
                                 throws java.io.IOException
Writes the "End of central dir record".

Throws:
java.io.IOException - on error

writeOut

protected final void writeOut(byte[] data)
                       throws java.io.IOException
Write bytes to output or random access file.

Parameters:
data - the byte array to write
Throws:
java.io.IOException - on error

writeOut

protected final void writeOut(byte[] data,
                              int offset,
                              int length)
                       throws java.io.IOException
Write bytes to output or random access file.

Parameters:
data - the byte array to write
offset - the start position to write from
length - the number of bytes to write
Throws:
java.io.IOException - on error

deflateUntilInputIsNeeded

private void deflateUntilInputIsNeeded()
                                throws java.io.IOException
Throws:
java.io.IOException

writeVersionNeededToExtractAndGeneralPurposeBits

private void writeVersionNeededToExtractAndGeneralPurposeBits(int zipMethod,
                                                              boolean utfFallback)
                                                       throws java.io.IOException
Throws:
java.io.IOException

createArchiveEntry

public ArchiveEntry createArchiveEntry(java.io.File inputFile,
                                       java.lang.String entryName)
                                throws java.io.IOException
Creates a new zip entry taking some information from the given file and using the provided name.

The name will be adjusted to end with a forward slash "/" if the file is a directory. If the file is not a directory a potential trailing forward slash will be stripped from the entry name.

Must not be used if the stream has already been closed.

Specified by:
createArchiveEntry in class ArchiveOutputStream
Returns:
the ArchiveEntry set up with details from the file
Throws:
java.io.IOException