public class ZipFile
extends java.lang.Object
implements java.io.Closeable
java.util.ZipFile
.
This class adds support for file name encodings other than UTF-8
(which is required to work on ZIP files created by native zip tools
and is able to skip a preamble like the one found in self
extracting archives. Furthermore it returns instances of
org.apache.commons.compress.archivers.zip.ZipArchiveEntry
instead of java.util.zip.ZipEntry
.
It doesn't extend java.util.zip.ZipFile
as it would
have to reimplement all methods anyway. Like
java.util.ZipFile
, it uses SeekableByteChannel under the
covers and supports compressed and uncompressed entries. As of
Apache Commons Compress 1.3 it also transparently supports Zip64
extensions and thus individual entries and archives larger than 4
GB or with more than 65536 entries.
The method signatures mimic the ones of
java.util.zip.ZipFile
, with a couple of exceptions:
org.apache.commons.compress.archivers.zip.ZipArchiveEntry
instances.Modifier and Type | Class and Description |
---|---|
private class |
ZipFile.BoundedFileChannelInputStream
Lock-free implementation of BoundedInputStream.
|
private class |
ZipFile.BoundedInputStream
InputStream that delegates requests to the underlying
SeekableByteChannel, making sure that only bytes from a certain
range can be read.
|
private static class |
ZipFile.Entry
Extends ZipArchiveEntry to store the offset within the archive.
|
private static class |
ZipFile.NameAndComment |
private static class |
ZipFile.StoredStatisticsStream |
Modifier and Type | Field and Description |
---|---|
private java.nio.channels.SeekableByteChannel |
archive
The actual data source.
|
private java.lang.String |
archiveName
File name of actual source.
|
(package private) static int |
BYTE_SHIFT |
private static int |
CFD_LOCATOR_OFFSET
Offset of the field that holds the location of the first
central directory entry inside the "End of central directory
record" relative to the start of the "End of central directory
record".
|
private static int |
CFH_LEN
Length of a "central directory" entry structure without file
name, extra fields or comment.
|
private static long |
CFH_SIG |
private java.nio.ByteBuffer |
cfhBbuf |
private byte[] |
cfhBuf |
private boolean |
closed
Whether the file is closed.
|
private java.nio.ByteBuffer |
dwordBbuf |
private byte[] |
dwordBuf |
private java.lang.String |
encoding
The encoding to use for filenames and the file comment.
|
private java.util.List<ZipArchiveEntry> |
entries
List of entries in the order they appear inside the central
directory.
|
private static int |
HASH_SIZE |
private static long |
LFH_OFFSET_FOR_FILENAME_LENGTH
Number of bytes in local file header up to the "length of
filename" entry.
|
private static int |
MAX_EOCD_SIZE
Maximum length of the "End of central directory record" with a
file comment.
|
(package private) static int |
MIN_EOCD_SIZE
Length of the "End of central directory record" - which is
supposed to be the last structure of the archive - without file
comment.
|
private java.util.Map<java.lang.String,java.util.LinkedList<ZipArchiveEntry>> |
nameMap
Maps String to list of ZipArchiveEntrys, name -> actual entries.
|
(package private) static int |
NIBLET_MASK |
private java.util.Comparator<ZipArchiveEntry> |
offsetComparator
Compares two ZipArchiveEntries based on their offset within the archive.
|
private static byte[] |
ONE_ZERO_BYTE |
private static int |
POS_0 |
private static int |
POS_1 |
private static int |
POS_2 |
private static int |
POS_3 |
private byte[] |
shortBuf |
private boolean |
useUnicodeExtraFields
Whether to look for and use Unicode extra fields.
|
private java.nio.ByteBuffer |
wordBbuf |
private byte[] |
wordBuf |
private static int |
ZIP64_EOCD_CFD_LOCATOR_OFFSET
Offset of the field that holds the location of the first
central directory entry inside the "Zip64 end of central
directory record" relative to the start of the "Zip64 end of
central directory record".
|
private static int |
ZIP64_EOCDL_LENGTH
Length of the "Zip64 end of central directory locator" - which
should be right in front of the "end of central directory
record" if one is present at all.
|
private static int |
ZIP64_EOCDL_LOCATOR_OFFSET
Offset of the field that holds the location of the "Zip64 end
of central directory record" inside the "Zip64 end of central
directory locator" relative to the start of the "Zip64 end of
central directory locator".
|
private ZipEncoding |
zipEncoding
The zip encoding to use for filenames and the file comment.
|
Modifier | Constructor and Description |
---|---|
|
ZipFile(java.io.File f)
Opens the given file for reading, assuming "UTF8" for file names.
|
|
ZipFile(java.io.File f,
java.lang.String encoding)
Opens the given file for reading, assuming the specified
encoding for file names and scanning for unicode extra fields.
|
|
ZipFile(java.io.File f,
java.lang.String encoding,
boolean useUnicodeExtraFields)
Opens the given file for reading, assuming the specified
encoding for file names.
|
|
ZipFile(java.nio.channels.SeekableByteChannel channel)
Opens the given channel for reading, assuming "UTF8" for file names.
|
|
ZipFile(java.nio.channels.SeekableByteChannel channel,
java.lang.String encoding)
Opens the given channel for reading, assuming the specified
encoding for file names.
|
|
ZipFile(java.nio.channels.SeekableByteChannel channel,
java.lang.String archiveName,
java.lang.String encoding,
boolean useUnicodeExtraFields)
Opens the given channel for reading, assuming the specified
encoding for file names.
|
private |
ZipFile(java.nio.channels.SeekableByteChannel channel,
java.lang.String archiveName,
java.lang.String encoding,
boolean useUnicodeExtraFields,
boolean closeOnError) |
|
ZipFile(java.lang.String name)
Opens the given file for reading, assuming "UTF8".
|
|
ZipFile(java.lang.String name,
java.lang.String encoding)
Opens the given file for reading, assuming the specified
encoding for file names, scanning unicode extra fields.
|
Modifier and Type | Method and Description |
---|---|
boolean |
canReadEntryData(ZipArchiveEntry ze)
Whether this class is able to read the given entry.
|
void |
close()
Closes the archive.
|
static void |
closeQuietly(ZipFile zipfile)
close a zipfile quietly; throw no io fault, do nothing
on a null parameter
|
void |
copyRawEntries(ZipArchiveOutputStream target,
ZipArchiveEntryPredicate predicate)
Transfer selected entries from this zipfile to a given #ZipArchiveOutputStream.
|
private ZipFile.BoundedInputStream |
createBoundedInputStream(long start,
long remaining)
Creates new BoundedInputStream, according to implementation of
underlying archive channel.
|
protected void |
finalize()
Ensures that the close method of this zipfile is called when
there are no more references to it.
|
java.lang.String |
getEncoding()
The encoding to use for filenames and the file comment.
|
java.util.Enumeration<ZipArchiveEntry> |
getEntries()
Returns all entries.
|
java.lang.Iterable<ZipArchiveEntry> |
getEntries(java.lang.String name)
Returns all named entries in the same order they appear within
the archive's central directory.
|
java.util.Enumeration<ZipArchiveEntry> |
getEntriesInPhysicalOrder()
Returns all entries in physical order.
|
java.lang.Iterable<ZipArchiveEntry> |
getEntriesInPhysicalOrder(java.lang.String name)
Returns all named entries in the same order their contents
appear within the archive.
|
ZipArchiveEntry |
getEntry(java.lang.String name)
Returns a named entry - or
null if no entry by
that name exists. |
java.io.InputStream |
getInputStream(ZipArchiveEntry ze)
Returns an InputStream for reading the contents of the given entry.
|
java.io.InputStream |
getRawInputStream(ZipArchiveEntry ze)
Expose the raw stream of the archive entry (compressed form).
|
java.lang.String |
getUnixSymlink(ZipArchiveEntry entry)
Convenience method to return the entry's content as a String if isUnixSymlink()
returns true for it, otherwise returns null.
|
private java.util.Map<ZipArchiveEntry,ZipFile.NameAndComment> |
populateFromCentralDirectory()
Reads the central directory of the given archive and populates
the internal tables with ZipArchiveEntry instances.
|
private void |
positionAtCentralDirectory()
Searches for either the "Zip64 end of central directory
locator" or the "End of central dir record", parses
it and positions the stream at the first central directory
record.
|
private void |
positionAtCentralDirectory32()
Parses the "End of central dir record" and positions
the stream at the first central directory record.
|
private void |
positionAtCentralDirectory64()
Parses the "Zip64 end of central directory locator",
finds the "Zip64 end of central directory record" using the
parsed information, parses that and positions the stream at the
first central directory record.
|
private void |
positionAtEndOfCentralDirectoryRecord()
Searches for the and positions the stream at the start of the
"End of central dir record".
|
private void |
readCentralDirectoryEntry(java.util.Map<ZipArchiveEntry,ZipFile.NameAndComment> noUTF8Flag)
Reads an individual entry of the central directory, creats an
ZipArchiveEntry from it and adds it to the global maps.
|
private void |
resolveLocalFileHeaderData(java.util.Map<ZipArchiveEntry,ZipFile.NameAndComment> entriesWithoutUTF8Flag)
Walks through all recorded entries and adds the data available
from the local file header.
|
private void |
setSizesAndOffsetFromZip64Extra(ZipArchiveEntry ze,
int diskStart)
If the entry holds a Zip64 extended information extra field,
read sizes from there if the entry's sizes are set to
0xFFFFFFFFF, do the same for the offset of the local file
header.
|
private void |
skipBytes(int count)
Skips the given number of bytes or throws an EOFException if
skipping failed.
|
private boolean |
startsWithLocalFileHeader()
Checks whether the archive starts with a LFH.
|
private boolean |
tryToLocateSignature(long minDistanceFromEnd,
long maxDistanceFromEnd,
byte[] sig)
Searches the archive backwards from minDistance to maxDistance
for the given signature, positions the RandomaccessFile right
at the signature if it has been found.
|
private static final int HASH_SIZE
static final int NIBLET_MASK
static final int BYTE_SHIFT
private static final int POS_0
private static final int POS_1
private static final int POS_2
private static final int POS_3
private static final byte[] ONE_ZERO_BYTE
private final java.util.List<ZipArchiveEntry> entries
private final java.util.Map<java.lang.String,java.util.LinkedList<ZipArchiveEntry>> nameMap
private final java.lang.String encoding
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.
private final ZipEncoding zipEncoding
private final java.lang.String archiveName
private final java.nio.channels.SeekableByteChannel archive
private final boolean useUnicodeExtraFields
private volatile boolean closed
private final byte[] dwordBuf
private final byte[] wordBuf
private final byte[] cfhBuf
private final byte[] shortBuf
private final java.nio.ByteBuffer dwordBbuf
private final java.nio.ByteBuffer wordBbuf
private final java.nio.ByteBuffer cfhBbuf
private static final int CFH_LEN
private static final long CFH_SIG
static final int MIN_EOCD_SIZE
private static final int MAX_EOCD_SIZE
private static final int CFD_LOCATOR_OFFSET
private static final int ZIP64_EOCDL_LENGTH
private static final int ZIP64_EOCDL_LOCATOR_OFFSET
private static final int ZIP64_EOCD_CFD_LOCATOR_OFFSET
private static final long LFH_OFFSET_FOR_FILENAME_LENGTH
private final java.util.Comparator<ZipArchiveEntry> offsetComparator
Won't return any meaningful results if one of the entries isn't part of the archive at all.
public ZipFile(java.io.File f) throws java.io.IOException
f
- the archive.java.io.IOException
- if an error occurs while reading the file.public ZipFile(java.lang.String name) throws java.io.IOException
name
- name of the archive.java.io.IOException
- if an error occurs while reading the file.public ZipFile(java.lang.String name, java.lang.String encoding) throws java.io.IOException
name
- name of the archive.encoding
- the encoding to use for file names, use null
for the platform's default encodingjava.io.IOException
- if an error occurs while reading the file.public ZipFile(java.io.File f, java.lang.String encoding) throws java.io.IOException
f
- the archive.encoding
- the encoding to use for file names, use null
for the platform's default encodingjava.io.IOException
- if an error occurs while reading the file.public ZipFile(java.io.File f, java.lang.String encoding, boolean useUnicodeExtraFields) throws java.io.IOException
f
- the archive.encoding
- the encoding to use for file names, use null
for the platform's default encodinguseUnicodeExtraFields
- whether to use InfoZIP Unicode
Extra Fields (if present) to set the file names.java.io.IOException
- if an error occurs while reading the file.public ZipFile(java.nio.channels.SeekableByteChannel channel) throws java.io.IOException
SeekableInMemoryByteChannel
allows you to read from an in-memory archive.
channel
- the archive.java.io.IOException
- if an error occurs while reading the file.public ZipFile(java.nio.channels.SeekableByteChannel channel, java.lang.String encoding) throws java.io.IOException
SeekableInMemoryByteChannel
allows you to read from an in-memory archive.
channel
- the archive.encoding
- the encoding to use for file names, use null
for the platform's default encodingjava.io.IOException
- if an error occurs while reading the file.public ZipFile(java.nio.channels.SeekableByteChannel channel, java.lang.String archiveName, java.lang.String encoding, boolean useUnicodeExtraFields) throws java.io.IOException
SeekableInMemoryByteChannel
allows you to read from an in-memory archive.
channel
- the archive.archiveName
- name of the archive, used for error messages only.encoding
- the encoding to use for file names, use null
for the platform's default encodinguseUnicodeExtraFields
- whether to use InfoZIP Unicode
Extra Fields (if present) to set the file names.java.io.IOException
- if an error occurs while reading the file.private ZipFile(java.nio.channels.SeekableByteChannel channel, java.lang.String archiveName, java.lang.String encoding, boolean useUnicodeExtraFields, boolean closeOnError) throws java.io.IOException
java.io.IOException
public java.lang.String getEncoding()
public void close() throws java.io.IOException
close
in interface java.io.Closeable
close
in interface java.lang.AutoCloseable
java.io.IOException
- if an error occurs closing the archive.public static void closeQuietly(ZipFile zipfile)
zipfile
- file to close, can be nullpublic java.util.Enumeration<ZipArchiveEntry> getEntries()
Entries will be returned in the same order they appear within the archive's central directory.
ZipArchiveEntry
instancespublic java.util.Enumeration<ZipArchiveEntry> getEntriesInPhysicalOrder()
Entries will be returned in the same order their contents appear within the archive.
ZipArchiveEntry
instancespublic ZipArchiveEntry getEntry(java.lang.String name)
null
if no entry by
that name exists.
If multiple entries with the same name exist the first entry in the archive's central directory by that name is returned.
name
- name of the entry.null
if not present.public java.lang.Iterable<ZipArchiveEntry> getEntries(java.lang.String name)
name
- name of the entry.public java.lang.Iterable<ZipArchiveEntry> getEntriesInPhysicalOrder(java.lang.String name)
name
- name of the entry.public boolean canReadEntryData(ZipArchiveEntry ze)
May return false if it is set up to use encryption or a compression method that hasn't been implemented yet.
ze
- the entrypublic java.io.InputStream getRawInputStream(ZipArchiveEntry ze)
This method does not relate to how/if we understand the payload in the stream, since we really only intend to move it on to somewhere else.
ze
- The entry to get the stream forpublic void copyRawEntries(ZipArchiveOutputStream target, ZipArchiveEntryPredicate predicate) throws java.io.IOException
This method transfers entries based on the central directory of the zip file.
target
- The zipArchiveOutputStream to write the entries topredicate
- A predicate that selects which entries to writejava.io.IOException
- on errorpublic java.io.InputStream getInputStream(ZipArchiveEntry ze) throws java.io.IOException
ze
- the entry to get the stream for.InputStreamStatistics
.java.io.IOException
- if unable to create an input stream from the zipentrypublic java.lang.String getUnixSymlink(ZipArchiveEntry entry) throws java.io.IOException
Convenience method to return the entry's content as a String if isUnixSymlink() returns true for it, otherwise returns null.
This method assumes the symbolic link's file name uses the same encoding that as been specified for this ZipFile.
entry
- ZipArchiveEntry object that represents the symbolic linkjava.io.IOException
- problem with content's input streamprotected void finalize() throws java.lang.Throwable
finalize
in class java.lang.Object
java.lang.Throwable
close()
private java.util.Map<ZipArchiveEntry,ZipFile.NameAndComment> populateFromCentralDirectory() throws java.io.IOException
The ZipArchiveEntrys will know all data that can be obtained from the central directory alone, but not the data that requires the local file header or additional data to be read.
java.io.IOException
private void readCentralDirectoryEntry(java.util.Map<ZipArchiveEntry,ZipFile.NameAndComment> noUTF8Flag) throws java.io.IOException
noUTF8Flag
- map used to collect entries that don't have
their UTF-8 flag set and whose name will be set by data read
from the local file header later. The current entry may be
added to this map.java.io.IOException
private void setSizesAndOffsetFromZip64Extra(ZipArchiveEntry ze, int diskStart) throws java.io.IOException
Ensures the Zip64 extra either knows both compressed and uncompressed size or neither of both as the internal logic in ExtraFieldUtils forces the field to create local header data even if they are never used - and here a field with only one size would be invalid.
java.io.IOException
private void positionAtCentralDirectory() throws java.io.IOException
java.io.IOException
private void positionAtCentralDirectory64() throws java.io.IOException
java.io.IOException
private void positionAtCentralDirectory32() throws java.io.IOException
java.io.IOException
private void positionAtEndOfCentralDirectoryRecord() throws java.io.IOException
java.io.IOException
private boolean tryToLocateSignature(long minDistanceFromEnd, long maxDistanceFromEnd, byte[] sig) throws java.io.IOException
java.io.IOException
private void skipBytes(int count) throws java.io.IOException
java.io.IOException
private void resolveLocalFileHeaderData(java.util.Map<ZipArchiveEntry,ZipFile.NameAndComment> entriesWithoutUTF8Flag) throws java.io.IOException
Also records the offsets for the data to read from the entries.
java.io.IOException
private boolean startsWithLocalFileHeader() throws java.io.IOException
java.io.IOException
private ZipFile.BoundedInputStream createBoundedInputStream(long start, long remaining)