Package org.apache.commons.compress.archivers.zip

# Class ZipArchiveOutputStream

java.lang.Object
java.io.OutputStream
java.io.FilterOutputStream
org.apache.commons.compress.archivers.ArchiveOutputStream<ZipArchiveEntry>
org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream

All Implemented Interfaces:
  `Closeable`, `Flushable`, `AutoCloseable`

Direct Known Subclasses:
  `JarArchiveOutputStream`

public class ZipArchiveOutputStream extends ArchiveOutputStream<ZipArchiveEntry>
Reimplementation of `java.util.zip.ZipOutputStream` to 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 `SeekableByteChannel` when it knows that the output is going to go to a file and no split archive shall be created.

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

As of Apache Commons Compress 1.3, the class transparently supports Zip64 extensions and thus individual entries and archives larger than 4 GB or with more than 65,536 entries in most cases but explicit control is provided via `setUseZip64(org.apache.commons.compress.archivers.zip.Zip64Mode)`. If the stream can not use SeekableByteChannel and you try to write a ZipArchiveEntry of unknown size, then Zip64 extensions will be disabled by default.

This class is not thread-safe

- ## Nested Class Summary

  Nested Classes
  Modifier and Type
  Class
  Description
  `static final class`
  `ZipArchiveOutputStream.UnicodeExtraFieldPolicy`
  enum that represents the possible policies for creating Unicode extra fields.

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `protected final Deflater`
  `def`
  This Deflater object is used for output.
  `static final int`
  `DEFAULT_COMPRESSION`
  Default compression level for deflated entries.
  `static final int`
  `DEFLATED`
  Compression method for deflated entries.
  `static final int`
  `EFS_FLAG`
  Deprecated.
  use `GeneralPurposeBit.UFT8_NAMES_FLAG` instead
  `protected boolean`
  `finished`
  Deprecated.
  See `ArchiveOutputStream.isFinished()` and `finish()`.
  `static final int`
  `STORED`
  Compression method for stored entries.

  ### Fields inherited from class java.io.FilterOutputStream

  `out`

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `ZipArchiveOutputStream(File file)`
  Creates a new ZIP OutputStream writing to a File.
  `ZipArchiveOutputStream(File file, long zipSplitSize)`
  Creates a split ZIP Archive.
  `ZipArchiveOutputStream(OutputStream out)`
  Creates a new ZIP OutputStream filtering the underlying stream.
  `ZipArchiveOutputStream(SeekableByteChannel channel)`
  Creates a new ZIP OutputStream writing to a SeekableByteChannel.
  `ZipArchiveOutputStream(Path path, long zipSplitSize)`
  Creates a split ZIP Archive.
  `ZipArchiveOutputStream(Path file, OpenOption... options)`
  Creates a new ZIP OutputStream writing to a Path.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `void`
  `addRawArchiveEntry(ZipArchiveEntry entry, InputStream rawStream)`
  Adds an archive entry with a raw input stream.
  `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.
  `ZipArchiveEntry`
  `createArchiveEntry(File inputFile, String entryName)`
  Creates a new ZIP entry taking some information from the given file and using the provided name.
  `ZipArchiveEntry`
  `createArchiveEntry(Path inputPath, String entryName, LinkOption... options)`
  Creates a new ZIP entry taking some information from the given file and using the provided name.
  `protected final void`
  `deflate()`
  Writes next block of compressed data to the output stream.
  `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.
  `long`
  `getBytesWritten()`
  Returns the total number of bytes written to this stream.
  `String`
  `getEncoding()`
  The encoding to use for file names 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(ZipArchiveEntry archiveEntry)`
  Writes the headers for an archive entry to the output stream.
  `void`
  `setComment(String comment)`
  Sets the file comment.
  `void`
  `setCreateUnicodeExtraFields(ZipArchiveOutputStream.UnicodeExtraFieldPolicy b)`
  Whether to create Unicode Extra Fields.
  `void`
  `setEncoding(String encoding)`
  The encoding to use for file names 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`
  `setUseZip64(Zip64Mode mode)`
  Whether Zip64 extensions will be used.
  `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 final void`
  `writeOut(byte[] data)`
  Write bytes to output or random access file.
  `protected final void`
  `writeOut(byte[] data, int offset, int length)`
  Write bytes to output or random access file.
  `void`
  `writePreamble(byte[] preamble)`
  Write preamble data.
  `void`
  `writePreamble(byte[] preamble, int offset, int length)`
  Write preamble data.
  `protected void`
  `writeZip64CentralDirectory()`
  Writes the "ZIP64 End of central dir record" and "ZIP64 End of central dir locator".

  ### Methods inherited from class org.apache.commons.compress.archivers.ArchiveOutputStream

  `checkFinished, checkOpen, count, count, getCount, isClosed, isFinished, write`

  ### Methods inherited from class java.io.FilterOutputStream

  `write`

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Field Details

  - ### 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

  - ### EFS_FLAG

    @Deprecated public static final int EFS_FLAG
    Deprecated.
    use `GeneralPurposeBit.UFT8_NAMES_FLAG` instead
    General purpose flag, which indicates that file names are written in UTF-8.
    See Also:
      - Constant Field Values

  - ### finished

    @Deprecated protected boolean finished
    Deprecated.
    See `ArchiveOutputStream.isFinished()` and `finish()`.
    Indicates if this archive is finished. protected for use in Jar implementation.

  - ### def

    protected final Deflater def
    This Deflater object is used for output.

- ## Constructor Details

  - ### ZipArchiveOutputStream

    public ZipArchiveOutputStream(File file) throws IOException
    Creates a new ZIP OutputStream writing to a File. Will use random access if possible.
    Parameters:
      `file` - the file to ZIP to
    Throws:
      `IOException` - on error

  - ### ZipArchiveOutputStream

    public ZipArchiveOutputStream(File file, long zipSplitSize) throws IOException
    Creates a split ZIP Archive.

    The files making up the archive will use Z01, Z02, ... extensions and the last part of it will be the given `file`.

    Even though the stream writes to a file this stream will behave as if no random access was possible. This means the sizes of stored entries need to be known before the actual entry data is written.

    Parameters:
      `file` - the file that will become the last part of the split archive
      `zipSplitSize` - maximum size of a single part of the split archive created by this stream. Must be between 64kB and about 4GB.
    Throws:
      `IOException` - on error
      `IllegalArgumentException` - if zipSplitSize is not in the required range
    Since:
      1.20

  - ### ZipArchiveOutputStream

    public ZipArchiveOutputStream(OutputStream out)
    Creates a new ZIP OutputStream filtering the underlying stream.
    Parameters:
      `out` - the outputstream to zip

  - ### ZipArchiveOutputStream

    public ZipArchiveOutputStream(Path path, long zipSplitSize) throws IOException
    Creates a split ZIP Archive.

    The files making up the archive will use Z01, Z02, ... extensions and the last part of it will be the given `file`.

    Even though the stream writes to a file this stream will behave as if no random access was possible. This means the sizes of stored entries need to be known before the actual entry data is written.

    Parameters:
      `path` - the path to the file that will become the last part of the split archive
      `zipSplitSize` - maximum size of a single part of the split archive created by this stream. Must be between 64kB and about 4GB.
    Throws:
      `IOException` - on error
      `IllegalArgumentException` - if zipSplitSize is not in the required range
    Since:
      1.22

  - ### ZipArchiveOutputStream

    public ZipArchiveOutputStream(Path file, OpenOption... options) throws IOException
    Creates a new ZIP OutputStream writing to a Path. Will use random access if possible.
    Parameters:
      `file` - the file to ZIP to
      `options` - options specifying how the file is opened.
    Throws:
      `IOException` - on error
    Since:
      1.21

  - ### ZipArchiveOutputStream

    public ZipArchiveOutputStream(SeekableByteChannel channel)
    Creates a new ZIP OutputStream writing to a SeekableByteChannel.

    `SeekableInMemoryByteChannel` allows you to write to an in-memory archive using random access.

    Parameters:
      `channel` - the channel to ZIP to
    Since:
      1.13

- ## Method Details

  - ### addRawArchiveEntry

    public void addRawArchiveEntry(ZipArchiveEntry entry, InputStream rawStream) throws IOException
    Adds an archive entry with a raw input stream.

    If crc, size and compressed size are supplied on the entry, these values will be used as-is. Zip64 status is re-established based on the settings in this stream, and the supplied value is ignored.

    The entry is put and closed immediately.

    Parameters:
      `entry` - The archive entry to add
      `rawStream` - The raw input stream of a different entry. May be compressed/encrypted.
    Throws:
      `IOException` - If copying fails

  - ### 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<ZipArchiveEntry>`
    Parameters:
      `ae` - the entry to test
    Returns:
      This implementation always returns true.
    Since:
      1.1

  - ### close

    public void close() throws IOException
    Closes this output stream and releases any system resources associated with the stream.
    Specified by:
      `close` in interface `AutoCloseable`
    Specified by:
      `close` in interface `Closeable`
    Overrides:
      `close` in class `ArchiveOutputStream<ZipArchiveEntry>`
    Throws:
      `IOException` - if an I/O error occurs.
      `Zip64RequiredException` - if the archive's size exceeds 4 GByte or there are more than 65535 entries inside the archive and `setUseZip64(org.apache.commons.compress.archivers.zip.Zip64Mode)` is `Zip64Mode.Never`.

  - ### closeArchiveEntry

    public void closeArchiveEntry() throws IOException
    Writes all necessary data for this entry.
    Specified by:
      `closeArchiveEntry` in class `ArchiveOutputStream<ZipArchiveEntry>`
    Throws:
      `IOException` - on error
      `Zip64RequiredException` - if the entry's uncompressed or compressed size exceeds 4 GByte and `setUseZip64(org.apache.commons.compress.archivers.zip.Zip64Mode)` is `Zip64Mode.Never`.

  - ### createArchiveEntry

    public ZipArchiveEntry createArchiveEntry(File inputFile, String entryName) throws 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<ZipArchiveEntry>`
    Parameters:
      `inputFile` - the file to create the entry from
      `entryName` - name to use for the entry
    Returns:
      the ArchiveEntry set up with details from the file
    Throws:
      `IOException` - if an I/O error occurs

  - ### createArchiveEntry

    public ZipArchiveEntry createArchiveEntry(Path inputPath, String entryName, LinkOption... options) throws 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.

    Overrides:
      `createArchiveEntry` in class `ArchiveOutputStream<ZipArchiveEntry>`
    Parameters:
      `inputPath` - path to create the entry from.
      `entryName` - name of the entry.
      `options` - options indicating how symbolic links are handled.
    Returns:
      a new instance.
    Throws:
      `IOException` - if an I/O error occurs.
    Since:
      1.21

  - ### deflate

    protected final void deflate() throws IOException
    Writes next block of compressed data to the output stream.
    Throws:
      `IOException` - on error

  - ### finish

    public void finish() throws IOException
    Finishes the addition of entries to this stream, without closing it. Additional data can be written, if the format supports it.
    Overrides:
      `finish` in class `ArchiveOutputStream<ZipArchiveEntry>`
    Throws:
      `Zip64RequiredException` - if the archive's size exceeds 4 GByte or there are more than 65535 entries inside the archive and `setUseZip64(org.apache.commons.compress.archivers.zip.Zip64Mode)` is `Zip64Mode.Never`.
      `IOException` - Maybe thrown by subclasses if the user forgets to close the entry.

  - ### flush

    public void flush() throws IOException
    Flushes this output stream and forces any buffered output bytes to be written out to the stream.
    Specified by:
      `flush` in interface `Flushable`
    Overrides:
      `flush` in class `FilterOutputStream`
    Throws:
      `IOException` - if an I/O error occurs.

  - ### getBytesWritten

    public long getBytesWritten()
    Returns the total number of bytes written to this stream.
    Overrides:
      `getBytesWritten` in class `ArchiveOutputStream<ZipArchiveEntry>`
    Returns:
      the number of written bytes
    Since:
      1.22

  - ### getEncoding

    public String getEncoding()
    The encoding to use for file names and the file comment.
    Returns:
      null if using the platform's default character encoding.

  - ### 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(ZipArchiveEntry)`.

    Returns:
      true if seekable

  - ### putArchiveEntry

    public void putArchiveEntry(ZipArchiveEntry archiveEntry) throws 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<ZipArchiveEntry>`
    Parameters:
      `archiveEntry` - describes the entry
    Throws:
      `ClassCastException` - if entry is not an instance of ZipArchiveEntry
      `Zip64RequiredException` - if the entry's uncompressed or compressed size is known to exceed 4 GByte and `setUseZip64(org.apache.commons.compress.archivers.zip.Zip64Mode)` is `Zip64Mode.Never`.
      `IOException` - if an I/O error occurs

  - ### setComment

    public void setComment(String comment)
    Sets the file comment.
    Parameters:
      `comment` - the comment

  - ### setCreateUnicodeExtraFields

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

    Defaults to NEVER.

    Parameters:
      `b` - whether to create Unicode Extra Fields.

  - ### setEncoding

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

    For a list of possible values see Supported Encodings. Defaults to UTF-8.

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

  - ### 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.

    Parameters:
      `b` - whether to fall back to UTF and the language encoding flag if the file name cannot be encoded using the specified encoding.

  - ### setLevel

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

    Default is Deflater.DEFAULT_COMPRESSION.

    Parameters:
      `level` - the compression level.
    Throws:
      `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

  - ### setUseLanguageEncodingFlag

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

    Defaults to true.

    Parameters:
      `b` - whether to set the language encoding flag if the file name encoding is UTF-8

  - ### setUseZip64

    public void setUseZip64(Zip64Mode mode)
    Whether Zip64 extensions will be used.

    When setting the mode to `Never`, `putArchiveEntry(org.apache.commons.compress.archivers.zip.ZipArchiveEntry)`, `closeArchiveEntry()`, `finish()` or `close()` may throw a `Zip64RequiredException` if the entry's size or the total size of the archive exceeds 4GB or there are more than 65,536 entries inside the archive. Any archive created in this mode will be readable by implementations that don't support Zip64.

    When setting the mode to `Always`, Zip64 extensions will be used for all entries. Any archive created in this mode may be unreadable by implementations that don't support Zip64 even if all its contents would be.

    When setting the mode to `AsNeeded`, Zip64 extensions will transparently be used for those entries that require them. This mode can only be used if the uncompressed size of the `ZipArchiveEntry` is known when calling `putArchiveEntry(org.apache.commons.compress.archivers.zip.ZipArchiveEntry)` or the archive is written to a seekable output (i.e. you have used the `File-arg constructor`) - this mode is not valid when the output stream is not seekable and the uncompressed size is unknown when `putArchiveEntry(org.apache.commons.compress.archivers.zip.ZipArchiveEntry)` is called.

    If no entry inside the resulting archive requires Zip64 extensions then `Never` will create the smallest archive. `AsNeeded` will create a slightly bigger archive if the uncompressed size of any entry has initially been unknown and create an archive identical to `Never` otherwise. `Always` will create an archive that is at least 24 bytes per entry bigger than the one `Never` would create.

    Defaults to `AsNeeded` unless `putArchiveEntry(org.apache.commons.compress.archivers.zip.ZipArchiveEntry)` is called with an entry of unknown size and data is written to a non-seekable stream - in this case the default is `Never`.

    Parameters:
      `mode` - Whether Zip64 extensions will be used.
    Since:
      1.3

  - ### write

    public void write(byte[] b, int offset, int length) throws IOException
    Writes bytes to ZIP entry.
    Overrides:
      `write` in class `FilterOutputStream`
    Parameters:
      `b` - the byte array to write
      `offset` - the start position to write from
      `length` - the number of bytes to write
    Throws:
      `IOException` - on error

  - ### writeCentralDirectoryEnd

    protected void writeCentralDirectoryEnd() throws IOException
    Writes the "End of central dir record".
    Throws:
      `IOException` - on error
      `Zip64RequiredException` - if the archive's size exceeds 4 GByte or there are more than 65535 entries inside the archive and `setUseZip64(Zip64Mode)` is `Zip64Mode.Never`.

  - ### writeCentralFileHeader

    protected void writeCentralFileHeader(ZipArchiveEntry ze) throws IOException
    Writes the central file header entry.
    Parameters:
      `ze` - the entry to write
    Throws:
      `IOException` - on error
      `Zip64RequiredException` - if the archive's size exceeds 4 GByte and `setUseZip64(Zip64Mode)` is `Zip64Mode.Never`.

  - ### writeDataDescriptor

    protected void writeDataDescriptor(ZipArchiveEntry ze) throws IOException
    Writes the data descriptor entry.
    Parameters:
      `ze` - the entry to write
    Throws:
      `IOException` - on error

  - ### writeLocalFileHeader

    protected void writeLocalFileHeader(ZipArchiveEntry ze) throws IOException
    Writes the local file header entry
    Parameters:
      `ze` - the entry to write
    Throws:
      `IOException` - on error

  - ### writeOut

    protected final void writeOut(byte[] data) throws IOException
    Write bytes to output or random access file.
    Parameters:
      `data` - the byte array to write
    Throws:
      `IOException` - on error

  - ### writeOut

    protected final void writeOut(byte[] data, int offset, int length) throws 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:
      `IOException` - on error

  - ### writePreamble

    public void writePreamble(byte[] preamble) throws IOException
    Write preamble data. For most of the time, this is used to make self-extracting zips.
    Parameters:
      `preamble` - data to write
    Throws:
      `IOException` - if an entry already exists
    Since:
      1.21

  - ### writePreamble

    public void writePreamble(byte[] preamble, int offset, int length) throws IOException
    Write preamble data. For most of the time, this is used to make self-extracting zips.
    Parameters:
      `preamble` - data to write
      `offset` - the start offset in the data
      `length` - the number of bytes to write
    Throws:
      `IOException` - if an entry already exists
    Since:
      1.21

  - ### writeZip64CentralDirectory

    protected void writeZip64CentralDirectory() throws IOException
    Writes the "ZIP64 End of central dir record" and "ZIP64 End of central dir locator".
    Throws:
      `IOException` - on error
    Since:
      1.3