Class AbstractLZ77CompressorInputStream

java.lang.Object
java.io.InputStream
org.apache.commons.compress.compressors.CompressorInputStream
org.apache.commons.compress.compressors.lz77support.AbstractLZ77CompressorInputStream
All Implemented Interfaces:
Closeable, AutoCloseable, InputStreamStatistics
Direct Known Subclasses:
BlockLZ4CompressorInputStream, SnappyCompressorInputStream

public abstract class AbstractLZ77CompressorInputStream extends CompressorInputStream implements InputStreamStatistics
Encapsulates code common to LZ77 decompressors.

Assumes the stream consists of blocks of literal data and back-references (called copies) in any order. Of course the first block must be a literal block for the scheme to work - unless the prefill method has been used to provide initial data that is never returned by read but only used for back-references.

Subclasses must override the three-arg read method as the no-arg version delegates to it and the default implementation delegates to the no-arg version, leading to infinite mutual recursion and a StackOverflowError otherwise.

The contract for subclasses' read implementation is:

  • keep track of the current state of the stream. Is it inside a literal block or a back-reference or in-between blocks?
  • Use readOneByte() to access the underlying stream directly.
  • If a new literal block starts, use startLiteral(long) to tell this class about it and read the literal data using readLiteral(byte[], int, int) until it returns 0. hasMoreDataInBlock() will return false before the next call to readLiteral(byte[], int, int) would return 0.
  • If a new back-reference starts, use startBackReference(int, long) to tell this class about it and read the literal data using readBackReference(byte[], int, int) until it returns 0. hasMoreDataInBlock() will return false before the next call to readBackReference(byte[], int, int) would return 0.
  • If the end of the stream has been reached, return -1 as this class' methods will never do so themselves.

readOneByte() and readLiteral(byte[], int, int) update the counter for bytes read.

Since:
1.14
  • Constructor Details

    • AbstractLZ77CompressorInputStream

      public AbstractLZ77CompressorInputStream(InputStream is, int windowSize)
      Creates a new LZ77 input stream.
      Parameters:
      is - An InputStream to read compressed data from
      windowSize - Size of the window kept for back-references, must be bigger than the biggest offset expected.
      Throws:
      IllegalArgumentException - if windowSize is not bigger than 0
  • Method Details

    • available

      public int available()
      Overrides:
      available in class InputStream
    • close

      public void close() throws IOException
      Specified by:
      close in interface AutoCloseable
      Specified by:
      close in interface Closeable
      Overrides:
      close in class InputStream
      Throws:
      IOException
    • getCompressedCount

      public long getCompressedCount()
      Specified by:
      getCompressedCount in interface InputStreamStatistics
      Returns:
      the amount of raw or compressed bytes read by the stream
      Since:
      1.17
    • getSize

      public int getSize()
      Get the uncompressed size of the stream
      Returns:
      the uncompressed size
    • prefill

      public void prefill(byte[] data)
      Adds some initial data to fill the window with.

      This is used if the stream has been cut into blocks and back-references of one block may refer to data of the previous block(s). One such example is the LZ4 frame format using block dependency.

      Parameters:
      data - the data to fill the window with.
      Throws:
      IllegalStateException - if the stream has already started to read data
    • read

      public int read() throws IOException
      Specified by:
      read in class InputStream
      Throws:
      IOException