Class SevenZFile

  • All Implemented Interfaces:
    java.io.Closeable, java.lang.AutoCloseable

    public class SevenZFile
    extends java.lang.Object
    implements java.io.Closeable
    Reads a 7z file, using SeekableByteChannel under the covers.

    The 7z file format is a flexible container that can contain many compression and encryption types, but at the moment only only Copy, LZMA, LZMA2, BZIP2, Deflate and AES-256 + SHA-256 are supported.

    The format is very Windows/Intel specific, so it uses little-endian byte order, doesn't store user/group or permission bits, and represents times using NTFS timestamps (100 nanosecond units since 1 January 1601). Hence the official tools recommend against using it for backup purposes on *nix, and recommend .tar.7z or .tar.lzma or .tar.xz instead.

    Both the header and file contents may be compressed and/or encrypted. With both encrypted, neither file names nor file contents can be read, but the use of encryption isn't plausibly deniable.

    Multi volume archives can be read by concatenating the parts in correct order - either manually or by using {link org.apache.commons.compress.utils.MultiReadOnlySeekableByteChannel} for example.

    Since:
    1.6
    • Field Detail

      • DEFAULT_FILE_NAME

        private static final java.lang.String DEFAULT_FILE_NAME
        See Also:
        Constant Field Values
      • fileName

        private final java.lang.String fileName
      • channel

        private java.nio.channels.SeekableByteChannel channel
      • archive

        private final Archive archive
      • currentEntryIndex

        private int currentEntryIndex
      • currentFolderIndex

        private int currentFolderIndex
      • currentFolderInputStream

        private java.io.InputStream currentFolderInputStream
      • password

        private byte[] password
      • compressedBytesReadFromCurrentEntry

        private long compressedBytesReadFromCurrentEntry
      • uncompressedBytesReadFromCurrentEntry

        private long uncompressedBytesReadFromCurrentEntry
      • deferredBlockStreams

        private final java.util.ArrayList<java.io.InputStream> deferredBlockStreams
      • sevenZSignature

        static final byte[] sevenZSignature
      • PASSWORD_ENCODER

        private static final java.nio.charset.CharsetEncoder PASSWORD_ENCODER
    • Constructor Detail

      • SevenZFile

        public SevenZFile​(java.io.File fileName,
                          char[] password)
                   throws java.io.IOException
        Reads a file as 7z archive
        Parameters:
        fileName - the file to read
        password - optional password if the archive is encrypted
        Throws:
        java.io.IOException - if reading the archive fails
        Since:
        1.17
      • SevenZFile

        public SevenZFile​(java.io.File fileName,
                          char[] password,
                          SevenZFileOptions options)
                   throws java.io.IOException
        Reads a file as 7z archive with additional options.
        Parameters:
        fileName - the file to read
        password - optional password if the archive is encrypted
        options - the options to apply
        Throws:
        java.io.IOException - if reading the archive fails or the memory limit (if set) is too small
        Since:
        1.19
      • SevenZFile

        @Deprecated
        public SevenZFile​(java.io.File fileName,
                          byte[] password)
                   throws java.io.IOException
        Deprecated.
        use the char[]-arg version for the password instead
        Reads a file as 7z archive
        Parameters:
        fileName - the file to read
        password - optional password if the archive is encrypted - the byte array is supposed to be the UTF16-LE encoded representation of the password.
        Throws:
        java.io.IOException - if reading the archive fails
      • SevenZFile

        public SevenZFile​(java.nio.channels.SeekableByteChannel channel)
                   throws java.io.IOException
        Reads a SeekableByteChannel as 7z archive

        SeekableInMemoryByteChannel allows you to read from an in-memory archive.

        Parameters:
        channel - the channel to read
        Throws:
        java.io.IOException - if reading the archive fails
        Since:
        1.13
      • SevenZFile

        public SevenZFile​(java.nio.channels.SeekableByteChannel channel,
                          SevenZFileOptions options)
                   throws java.io.IOException
        Reads a SeekableByteChannel as 7z archive with addtional options.

        SeekableInMemoryByteChannel allows you to read from an in-memory archive.

        Parameters:
        channel - the channel to read
        options - the options to apply
        Throws:
        java.io.IOException - if reading the archive fails or the memory limit (if set) is too small
        Since:
        1.19
      • SevenZFile

        public SevenZFile​(java.nio.channels.SeekableByteChannel channel,
                          char[] password)
                   throws java.io.IOException
        Reads a SeekableByteChannel as 7z archive

        SeekableInMemoryByteChannel allows you to read from an in-memory archive.

        Parameters:
        channel - the channel to read
        password - optional password if the archive is encrypted
        Throws:
        java.io.IOException - if reading the archive fails
        Since:
        1.17
      • SevenZFile

        public SevenZFile​(java.nio.channels.SeekableByteChannel channel,
                          char[] password,
                          SevenZFileOptions options)
                   throws java.io.IOException
        Reads a SeekableByteChannel as 7z archive with additional options.

        SeekableInMemoryByteChannel allows you to read from an in-memory archive.

        Parameters:
        channel - the channel to read
        password - optional password if the archive is encrypted
        options - the options to apply
        Throws:
        java.io.IOException - if reading the archive fails or the memory limit (if set) is too small
        Since:
        1.19
      • SevenZFile

        public SevenZFile​(java.nio.channels.SeekableByteChannel channel,
                          java.lang.String fileName,
                          char[] password)
                   throws java.io.IOException
        Reads a SeekableByteChannel as 7z archive

        SeekableInMemoryByteChannel allows you to read from an in-memory archive.

        Parameters:
        channel - the channel to read
        fileName - name of the archive - only used for error reporting
        password - optional password if the archive is encrypted
        Throws:
        java.io.IOException - if reading the archive fails
        Since:
        1.17
      • SevenZFile

        public SevenZFile​(java.nio.channels.SeekableByteChannel channel,
                          java.lang.String fileName,
                          char[] password,
                          SevenZFileOptions options)
                   throws java.io.IOException
        Reads a SeekableByteChannel as 7z archive with addtional options.

        SeekableInMemoryByteChannel allows you to read from an in-memory archive.

        Parameters:
        channel - the channel to read
        fileName - name of the archive - only used for error reporting
        password - optional password if the archive is encrypted
        options - the options to apply
        Throws:
        java.io.IOException - if reading the archive fails or the memory limit (if set) is too small
        Since:
        1.19
      • SevenZFile

        public SevenZFile​(java.nio.channels.SeekableByteChannel channel,
                          java.lang.String fileName)
                   throws java.io.IOException
        Reads a SeekableByteChannel as 7z archive

        SeekableInMemoryByteChannel allows you to read from an in-memory archive.

        Parameters:
        channel - the channel to read
        fileName - name of the archive - only used for error reporting
        Throws:
        java.io.IOException - if reading the archive fails
        Since:
        1.17
      • SevenZFile

        public SevenZFile​(java.nio.channels.SeekableByteChannel channel,
                          java.lang.String fileName,
                          SevenZFileOptions options)
                   throws java.io.IOException
        Reads a SeekableByteChannel as 7z archive with additional options.

        SeekableInMemoryByteChannel allows you to read from an in-memory archive.

        Parameters:
        channel - the channel to read
        fileName - name of the archive - only used for error reporting
        options - the options to apply
        Throws:
        java.io.IOException - if reading the archive fails or the memory limit (if set) is too small
        Since:
        1.19
      • SevenZFile

        @Deprecated
        public SevenZFile​(java.nio.channels.SeekableByteChannel channel,
                          byte[] password)
                   throws java.io.IOException
        Deprecated.
        use the char[]-arg version for the password instead
        Reads a SeekableByteChannel as 7z archive

        SeekableInMemoryByteChannel allows you to read from an in-memory archive.

        Parameters:
        channel - the channel to read
        password - optional password if the archive is encrypted - the byte array is supposed to be the UTF16-LE encoded representation of the password.
        Throws:
        java.io.IOException - if reading the archive fails
        Since:
        1.13
      • SevenZFile

        @Deprecated
        public SevenZFile​(java.nio.channels.SeekableByteChannel channel,
                          java.lang.String fileName,
                          byte[] password)
                   throws java.io.IOException
        Deprecated.
        use the char[]-arg version for the password instead
        Reads a SeekableByteChannel as 7z archive

        SeekableInMemoryByteChannel allows you to read from an in-memory archive.

        Parameters:
        channel - the channel to read
        fileName - name of the archive - only used for error reporting
        password - optional password if the archive is encrypted - the byte array is supposed to be the UTF16-LE encoded representation of the password.
        Throws:
        java.io.IOException - if reading the archive fails
        Since:
        1.13
      • SevenZFile

        private SevenZFile​(java.nio.channels.SeekableByteChannel channel,
                           java.lang.String filename,
                           byte[] password,
                           boolean closeOnError,
                           SevenZFileOptions options)
                    throws java.io.IOException
        Throws:
        java.io.IOException
      • SevenZFile

        public SevenZFile​(java.io.File fileName)
                   throws java.io.IOException
        Reads a file as unencrypted 7z archive
        Parameters:
        fileName - the file to read
        Throws:
        java.io.IOException - if reading the archive fails
      • SevenZFile

        public SevenZFile​(java.io.File fileName,
                          SevenZFileOptions options)
                   throws java.io.IOException
        Reads a file as unencrypted 7z archive
        Parameters:
        fileName - the file to read
        options - the options to apply
        Throws:
        java.io.IOException - if reading the archive fails or the memory limit (if set) is too small
        Since:
        1.19
    • Method Detail

      • close

        public void close()
                   throws java.io.IOException
        Closes the archive.
        Specified by:
        close in interface java.lang.AutoCloseable
        Specified by:
        close in interface java.io.Closeable
        Throws:
        java.io.IOException - if closing the file fails
      • getNextEntry

        public SevenZArchiveEntry getNextEntry()
                                        throws java.io.IOException
        Returns the next Archive Entry in this archive.
        Returns:
        the next entry, or null if there are no more entries
        Throws:
        java.io.IOException - if the next entry could not be read
      • getEntries

        public java.lang.Iterable<SevenZArchiveEntry> getEntries()
        Returns a copy of meta-data of all archive entries.

        This method only provides meta-data, the entries can not be used to read the contents, you still need to process all entries in order using getNextEntry() for that.

        The content methods are only available for entries that have already been reached via getNextEntry().

        Returns:
        a copy of meta-data of all archive entries.
        Since:
        1.11
      • readHeaders

        private Archive readHeaders​(byte[] password)
                             throws java.io.IOException
        Throws:
        java.io.IOException
      • tryToLocateEndHeader

        private Archive tryToLocateEndHeader​(byte[] password)
                                      throws java.io.IOException
        Throws:
        java.io.IOException
      • initializeArchive

        private Archive initializeArchive​(StartHeader startHeader,
                                          byte[] password,
                                          boolean verifyCrc)
                                   throws java.io.IOException
        Throws:
        java.io.IOException
      • readStartHeader

        private StartHeader readStartHeader​(long startHeaderCrc)
                                     throws java.io.IOException
        Throws:
        java.io.IOException
      • readHeader

        private void readHeader​(java.nio.ByteBuffer header,
                                Archive archive)
                         throws java.io.IOException
        Throws:
        java.io.IOException
      • sanityCheckAndCollectStatistics

        private SevenZFile.ArchiveStatistics sanityCheckAndCollectStatistics​(java.nio.ByteBuffer header)
                                                                      throws java.io.IOException
        Throws:
        java.io.IOException
      • readArchiveProperties

        private void readArchiveProperties​(java.nio.ByteBuffer input)
                                    throws java.io.IOException
        Throws:
        java.io.IOException
      • sanityCheckArchiveProperties

        private void sanityCheckArchiveProperties​(java.nio.ByteBuffer header)
                                           throws java.io.IOException
        Throws:
        java.io.IOException
      • readEncodedHeader

        private java.nio.ByteBuffer readEncodedHeader​(java.nio.ByteBuffer header,
                                                      Archive archive,
                                                      byte[] password)
                                               throws java.io.IOException
        Throws:
        java.io.IOException
      • sanityCheckStreamsInfo

        private void sanityCheckStreamsInfo​(java.nio.ByteBuffer header,
                                            SevenZFile.ArchiveStatistics stats)
                                     throws java.io.IOException
        Throws:
        java.io.IOException
      • readStreamsInfo

        private void readStreamsInfo​(java.nio.ByteBuffer header,
                                     Archive archive)
                              throws java.io.IOException
        Throws:
        java.io.IOException
      • sanityCheckPackInfo

        private void sanityCheckPackInfo​(java.nio.ByteBuffer header,
                                         SevenZFile.ArchiveStatistics stats)
                                  throws java.io.IOException
        Throws:
        java.io.IOException
      • readPackInfo

        private void readPackInfo​(java.nio.ByteBuffer header,
                                  Archive archive)
                           throws java.io.IOException
        Throws:
        java.io.IOException
      • sanityCheckUnpackInfo

        private void sanityCheckUnpackInfo​(java.nio.ByteBuffer header,
                                           SevenZFile.ArchiveStatistics stats)
                                    throws java.io.IOException
        Throws:
        java.io.IOException
      • readUnpackInfo

        private void readUnpackInfo​(java.nio.ByteBuffer header,
                                    Archive archive)
                             throws java.io.IOException
        Throws:
        java.io.IOException
      • sanityCheckSubStreamsInfo

        private void sanityCheckSubStreamsInfo​(java.nio.ByteBuffer header,
                                               SevenZFile.ArchiveStatistics stats)
                                        throws java.io.IOException
        Throws:
        java.io.IOException
      • readSubStreamsInfo

        private void readSubStreamsInfo​(java.nio.ByteBuffer header,
                                        Archive archive)
                                 throws java.io.IOException
        Throws:
        java.io.IOException
      • sanityCheckFolder

        private int sanityCheckFolder​(java.nio.ByteBuffer header,
                                      SevenZFile.ArchiveStatistics stats)
                               throws java.io.IOException
        Throws:
        java.io.IOException
      • readFolder

        private Folder readFolder​(java.nio.ByteBuffer header)
                           throws java.io.IOException
        Throws:
        java.io.IOException
      • readAllOrBits

        private java.util.BitSet readAllOrBits​(java.nio.ByteBuffer header,
                                               int size)
                                        throws java.io.IOException
        Throws:
        java.io.IOException
      • readBits

        private java.util.BitSet readBits​(java.nio.ByteBuffer header,
                                          int size)
                                   throws java.io.IOException
        Throws:
        java.io.IOException
      • sanityCheckFilesInfo

        private void sanityCheckFilesInfo​(java.nio.ByteBuffer header,
                                          SevenZFile.ArchiveStatistics stats)
                                   throws java.io.IOException
        Throws:
        java.io.IOException
      • readFilesInfo

        private void readFilesInfo​(java.nio.ByteBuffer header,
                                   Archive archive)
                            throws java.io.IOException
        Throws:
        java.io.IOException
      • checkEntryIsInitialized

        private void checkEntryIsInitialized​(java.util.Map<java.lang.Integer,​SevenZArchiveEntry> archiveEntries,
                                             int index)
      • calculateStreamMap

        private void calculateStreamMap​(Archive archive)
                                 throws java.io.IOException
        Throws:
        java.io.IOException
      • buildDecodingStream

        private void buildDecodingStream​(int entryIndex,
                                         boolean isRandomAccess)
                                  throws java.io.IOException
        Build the decoding stream for the entry to be read. This method may be called from a random access(getInputStream) or sequential access(getNextEntry). If this method is called from a random access, some entries may need to be skipped(we put them to the deferredBlockStreams and skip them when actually needed to improve the performance)
        Parameters:
        entryIndex - the index of the entry to be read
        isRandomAccess - is this called in a random access
        Throws:
        java.io.IOException - if there are exceptions when reading the file
      • reopenFolderInputStream

        private void reopenFolderInputStream​(int folderIndex,
                                             SevenZArchiveEntry file)
                                      throws java.io.IOException
        Discard any queued streams/ folder stream, and reopen the current folder input stream.
        Parameters:
        folderIndex - the index of the folder to reopen
        file - the 7z entry to read
        Throws:
        java.io.IOException - if exceptions occur when reading the 7z file
      • skipEntriesWhenNeeded

        private boolean skipEntriesWhenNeeded​(int entryIndex,
                                              boolean isInSameFolder,
                                              int folderIndex)
                                       throws java.io.IOException
        Skip all the entries if needed. Entries need to be skipped when:

        1. it's a random access 2. one of these 2 condition is meet :

        2.1 currentEntryIndex != entryIndex : this means there are some entries to be skipped(currentEntryIndex < entryIndex) or the entry has already been read(currentEntryIndex > entryIndex)

        2.2 currentEntryIndex == entryIndex && !hasCurrentEntryBeenRead: if the entry to be read is the current entry, but some data of it has been read before, then we need to reopen the stream of the folder and skip all the entries before the current entries

        Parameters:
        entryIndex - the entry to be read
        isInSameFolder - are the entry to be read and the current entry in the same folder
        folderIndex - the index of the folder which contains the entry
        Returns:
        true if there are entries actually skipped
        Throws:
        java.io.IOException - there are exceptions when skipping entries
        Since:
        1.21
      • hasCurrentEntryBeenRead

        private boolean hasCurrentEntryBeenRead()
        Find out if any data of current entry has been read or not. This is achieved by comparing the bytes remaining to read and the size of the file.
        Returns:
        true if any data of current entry has been read
        Since:
        1.21
      • buildDecoderStack

        private java.io.InputStream buildDecoderStack​(Folder folder,
                                                      long folderOffset,
                                                      int firstPackStreamIndex,
                                                      SevenZArchiveEntry entry)
                                               throws java.io.IOException
        Throws:
        java.io.IOException
      • read

        public int read()
                 throws java.io.IOException
        Reads a byte of data.
        Returns:
        the byte read, or -1 if end of input is reached
        Throws:
        java.io.IOException - if an I/O error has occurred
      • getCurrentStream

        private java.io.InputStream getCurrentStream()
                                              throws java.io.IOException
        Throws:
        java.io.IOException
      • getInputStream

        public java.io.InputStream getInputStream​(SevenZArchiveEntry entry)
                                           throws java.io.IOException
        Returns an InputStream for reading the contents of the given entry.

        For archives using solid compression randomly accessing entries will be significantly slower than reading the archive sequentially.

        Parameters:
        entry - the entry to get the stream for.
        Returns:
        a stream to read the entry from.
        Throws:
        java.io.IOException - if unable to create an input stream from the zipentry
        Since:
        Compress 1.20
      • read

        public int read​(byte[] b)
                 throws java.io.IOException
        Reads data into an array of bytes.
        Parameters:
        b - the array to write data to
        Returns:
        the number of bytes read, or -1 if end of input is reached
        Throws:
        java.io.IOException - if an I/O error has occurred
      • read

        public int read​(byte[] b,
                        int off,
                        int len)
                 throws java.io.IOException
        Reads data into an array of bytes.
        Parameters:
        b - the array to write data to
        off - offset into the buffer to start filling at
        len - of bytes to read
        Returns:
        the number of bytes read, or -1 if end of input is reached
        Throws:
        java.io.IOException - if an I/O error has occurred
      • getStatisticsForCurrentEntry

        public InputStreamStatistics getStatisticsForCurrentEntry()
        Provides statistics for bytes read from the current entry.
        Returns:
        statistics for bytes read from the current entry
        Since:
        1.17
      • readUint64

        private static long readUint64​(java.nio.ByteBuffer in)
                                throws java.io.IOException
        Throws:
        java.io.IOException
      • getChar

        private static char getChar​(java.nio.ByteBuffer buf)
                             throws java.io.IOException
        Throws:
        java.io.IOException
      • getInt

        private static int getInt​(java.nio.ByteBuffer buf)
                           throws java.io.IOException
        Throws:
        java.io.IOException
      • getLong

        private static long getLong​(java.nio.ByteBuffer buf)
                             throws java.io.IOException
        Throws:
        java.io.IOException
      • get

        private static void get​(java.nio.ByteBuffer buf,
                                byte[] to)
                         throws java.io.IOException
        Throws:
        java.io.IOException
      • getUnsignedByte

        private static int getUnsignedByte​(java.nio.ByteBuffer buf)
                                    throws java.io.IOException
        Throws:
        java.io.IOException
      • matches

        public static boolean matches​(byte[] signature,
                                      int length)
        Checks if the signature matches what is expected for a 7z file.
        Parameters:
        signature - the bytes to check
        length - the number of bytes to check
        Returns:
        true, if this is the signature of a 7z archive.
        Since:
        1.8
      • skipBytesFully

        private static long skipBytesFully​(java.nio.ByteBuffer input,
                                           long bytesToSkip)
                                    throws java.io.IOException
        Throws:
        java.io.IOException
      • readFully

        private void readFully​(java.nio.ByteBuffer buf)
                        throws java.io.IOException
        Throws:
        java.io.IOException
      • toString

        public java.lang.String toString()
        Overrides:
        toString in class java.lang.Object
      • getDefaultName

        public java.lang.String getDefaultName()
        Derives a default file name from the archive name - if known.

        This implements the same heuristics the 7z tools use. In 7z's case if an archive contains entries without a name - i.e. SevenZArchiveEntry.getName() returns null - then its command line and GUI tools will use this default name when extracting the entries.

        Returns:
        null if the name of the archive is unknown. Otherwise if the name of the archive has got any extension, it is stripped and the remainder returned. Finally if the name of the archive hasn't got any extension then a ~ character is appended to the archive name.
        Since:
        1.19
      • utf16Decode

        private static byte[] utf16Decode​(char[] chars)
                                   throws java.io.IOException
        Throws:
        java.io.IOException
      • assertFitsIntoNonNegativeInt

        private static int assertFitsIntoNonNegativeInt​(java.lang.String what,
                                                        long value)
                                                 throws java.io.IOException
        Throws:
        java.io.IOException