Top Description Fields Constructors Methods
org.tukaani.xz

public Class SeekableXZInputStream

extends SeekableInputStream
Class Inheritance
Imports
java.util.Arrays, .ArrayList, java.io.DataInputStream, .IOException, .EOFException, org.tukaani.xz.common.DecoderUtil, .StreamFlags, org.tukaani.xz.check.Check, org.tukaani.xz.index.IndexDecoder, .BlockInfo

Decompresses a .xz file in random access mode. This supports decompressing concatenated .xz files.

Each .xz file consist of one or more Streams. Each Stream consist of zero or more Blocks. Each Stream contains an Index of Streams' Blocks. The Indexes from all Streams are loaded in RAM by a constructor of this class. A typical .xz file has only one Stream, and parsing its Index will need only three or four seeks.

To make random access possible, the data in a .xz file must be splitted into multiple Blocks of reasonable size. Decompression can only start at a Block boundary. When seeking to an uncompressed position that is not at a Block boundary, decompression starts at the beginning of the Block and throws away data until the target position is reached. Thus, smaller Blocks mean faster seeks to arbitrary uncompressed positions. On the other hand, smaller Blocks mean worse compression. So one has to make a compromise between random access speed and compression ratio.

Implementation Note

This class uses linear search to locate the correct Stream from the data structures in RAM. It was the simplest to implement and should be fine as long as there aren't too many Streams. The correct Block inside a Stream is located using binary search and thus is fast even with a huge number of Blocks.

Memory usage

The amount of memory needed for the Indexes is taken into account when checking the memory usage limit. Each Stream is calculated to need at least 1 KiB of memory and each Block 16 bytes of memory, rounded up to the next kibibyte. So unless the file has a huge number of Streams or Blocks, these don't take significant amount of memory.

Creating random-accessible .xz files

When using XZOutputStream, a new Block can be started by calling its endBlock method. If you know that the decompressor will only need to seek to certain uncompressed positions, it can be a good idea to start a new Block at (some of) these positions (and only at these positions to get better compression ratio).

liblzma in XZ Utils supports starting a new Block with LZMA_FULL_FLUSH. XZ Utils 5.1.1alpha added threaded compression which creates multi-Block .xz files. XZ Utils 5.1.1alpha also added the option --block-size=SIZE to the xz command line tool. XZ Utils 5.1.2alpha added a partial implementation of --block-list=SIZES which allows specifying sizes of individual Blocks.

Example: getting the uncompressed size of a .xz file

String filename = "foo.xz";
SeekableFileInputStream seekableFile
        = new SeekableFileInputStream(filename);

try {
    SeekableXZInputStream seekableXZ
            = new SeekableXZInputStream(seekableFile);
    System.out.println("Uncompressed size: " + seekableXZ.length());
} finally {
    seekableFile.close();
}
See Also
SeekableFileInputStream, XZInputStream, XZOutputStream

Field Summary

Modifier and TypeField and Description
private final ArrayCache
arrayCache

Cache for big arrays.

private int
blockCount

Number of XZ Blocks in the file.

private BlockInputStream
blockDecoder

Decoder of the current XZ Block, if any.

private Check
check

Integrity Check in the current XZ Stream.

private int
checkTypes

Bitmask of all Check IDs seen.

private final BlockInfo
curBlockInfo

Size and position information about the current Block.

private long
curPos

Current uncompressed position.

private boolean
endReached

True when end of the file was reached.

private IOException
exception

Pending exception from an earlier error.

private SeekableInputStream
in

The input stream containing XZ compressed data.

private int
indexMemoryUsage

Memory usage of the IndexDecoders.

private long
largestBlockSize

Uncompressed size of the largest XZ Block in the file.

private final int
memoryLimit

Memory usage limit after the memory usage of the IndexDecoders have been substracted.

private final BlockInfo
queriedBlockInfo

Temporary (and cached) information about the Block whose information is queried via getBlockPos and related functions.

private boolean
seekNeeded

True when seek(long) has been called but the actual seeking hasn't been done yet.

private long
seekPos

Target position for seeking.

private final ArrayList<IndexDecoder>
streams

List of IndexDecoders, one for each Stream in the file.

private final byte[]
tempBuf

Temporary buffer for read().

private long
uncompressedSize

Uncompressed size of the file (all Streams).

private final boolean
verifyCheck

Flag indicating if the integrity checks will be verified.

Constructor Summary

AccessConstructor and Description
public
SeekableXZInputStream(SeekableInputStream
seekable input stream containing one or more XZ Streams; the whole input stream is used
in
)

Creates a new seekable XZ decompressor without a memory usage limit.

public
SeekableXZInputStream(SeekableInputStream
seekable input stream containing one or more XZ Streams; the whole input stream is used
in
,
ArrayCache
cache to be used for allocating large arrays
arrayCache
)

Creates a new seekable XZ decompressor without a memory usage limit.

public
SeekableXZInputStream(SeekableInputStream
seekable input stream containing one or more XZ Streams; the whole input stream is used
in
,
int
memory usage limit in kibibytes (KiB) or -1 to impose no memory usage limit
memoryLimit
)

Creates a new seekable XZ decomporessor with an optional memory usage limit.

public
SeekableXZInputStream(SeekableInputStream
seekable input stream containing one or more XZ Streams; the whole input stream is used
in
,
int
memory usage limit in kibibytes (KiB) or -1 to impose no memory usage limit
memoryLimit
,
ArrayCache
cache to be used for allocating large arrays
arrayCache
)

Creates a new seekable XZ decomporessor with an optional memory usage limit.

public
SeekableXZInputStream(SeekableInputStream
seekable input stream containing one or more XZ Streams; the whole input stream is used
in
,
int
memory usage limit in kibibytes (KiB) or -1 to impose no memory usage limit
memoryLimit
,
boolean
if true, the integrity checks will be verified; this should almost never be set to false
verifyCheck
)

Creates a new seekable XZ decomporessor with an optional memory usage limit and ability to disable verification of integrity checks.

public
SeekableXZInputStream(SeekableInputStream
seekable input stream containing one or more XZ Streams; the whole input stream is used
in
,
int
memory usage limit in kibibytes (KiB) or -1 to impose no memory usage limit
memoryLimit
,
boolean
if true, the integrity checks will be verified; this should almost never be set to false
verifyCheck
,
ArrayCache
cache to be used for allocating large arrays
arrayCache
)

Creates a new seekable XZ decomporessor with an optional memory usage limit and ability to disable verification of integrity checks.

Method Summary

Modifier and TypeMethod and Description
public int

Returns:

the number of uncompressed bytes that can be read without blocking
available
()

Overrides java.io.InputStream.available.

Returns the number of uncompressed bytes that can be read without blocking.
public void
close()

Overrides java.io.InputStream.close.

Implements java.io.Closeable.close.

Closes the stream and calls in.close().
public void
close(boolean closeInput)

Closes the stream and optionally calls in.close().

public int
getBlockCheckType(int blockNumber)

Gets integrity check type (Check ID) of the given Block.

public long
getBlockCompPos(int blockNumber)

Gets the position where the given compressed Block starts in the underlying .xz file.

public long
getBlockCompSize(int blockNumber)

Gets the compressed size of the given Block.

public int
getBlockCount()

Gets the number of Blocks in the .xz file.

public int
getBlockNumber(long pos)

Gets the number of the Block that contains the byte at the given uncompressed position.

public long
getBlockPos(int blockNumber)

Gets the uncompressed start position of the given Block.

public long
getBlockSize(int blockNumber)

Gets the uncompressed size of the given Block.

public int
getCheckTypes()

Gets the types of integrity checks used in the .xz file.

public int
getIndexMemoryUsage()

Gets the amount of memory in kibibytes (KiB) used by the data structures needed to locate the XZ Blocks.

public long
getLargestBlockSize()

Gets the uncompressed size of the largest XZ Block in bytes.

public int
getStreamCount()

Gets the number of Streams in the .xz file.

private void
initBlockDecoder()

Initializes a new BlockInputStream.

public long
length()

Implements abstract org.tukaani.xz.SeekableInputStream.length.

Gets the uncompressed size of this input stream.
private void
locateBlockByNumber(BlockInfo info, int blockNumber)

Locates the given Block and stores information about it to info.

private void
locateBlockByPos(BlockInfo info, long pos)

Locates the Block that contains the given uncompressed position.

public long
position()

Implements abstract org.tukaani.xz.SeekableInputStream.position.

Gets the current uncompressed position in this input stream.
public int

Returns:

the next decompressed byte, or -1 to indicate the end of the compressed stream
read
()

Implements abstract java.io.InputStream.read.

Decompresses the next byte from this input stream.
public int

Returns:

number of bytes read, or -1 to indicate the end of the compressed stream
read
(byte[]
target buffer for uncompressed data
buf
,
int
start offset in buf
off
,
int
maximum number of uncompressed bytes to read
len
)

Overrides java.io.InputStream.read.

Decompresses into an array of bytes.
public void
seek(long
new uncompressed read position
pos
)

Implements abstract org.tukaani.xz.SeekableInputStream.seek.

Seeks to the specified absolute uncompressed position in the stream.
private void
seek()

Does the actual seeking.

public void
seekToBlock(int blockNumber)

Seeks to the beginning of the given XZ Block.

Inherited from org.tukaani.xz.SeekableInputStream:
skip

Field Detail

arrayCacheback to summary
private final ArrayCache arrayCache

Cache for big arrays.

blockCountback to summary
private int blockCount

Number of XZ Blocks in the file.

blockDecoderback to summary
private BlockInputStream blockDecoder

Decoder of the current XZ Block, if any.

checkback to summary
private Check check

Integrity Check in the current XZ Stream. The constructor leaves this to point to the Check of the first Stream.

checkTypesback to summary
private int checkTypes

Bitmask of all Check IDs seen.

curBlockInfoback to summary
private final BlockInfo curBlockInfo

Size and position information about the current Block. If there are no Blocks, all values will be -1.

curPosback to summary
private long curPos

Current uncompressed position.

endReachedback to summary
private boolean endReached

True when end of the file was reached. This can be cleared by calling seek(long).

exceptionback to summary
private IOException exception

Pending exception from an earlier error.

inback to summary
private SeekableInputStream in

The input stream containing XZ compressed data.

indexMemoryUsageback to summary
private int indexMemoryUsage

Memory usage of the IndexDecoders. memoryLimit + indexMemoryUsage equals the original memory usage limit that was passed to the constructor.

largestBlockSizeback to summary
private long largestBlockSize

Uncompressed size of the largest XZ Block in the file.

memoryLimitback to summary
private final int memoryLimit

Memory usage limit after the memory usage of the IndexDecoders have been substracted.

queriedBlockInfoback to summary
private final BlockInfo queriedBlockInfo

Temporary (and cached) information about the Block whose information is queried via getBlockPos and related functions.

seekNeededback to summary
private boolean seekNeeded

True when seek(long) has been called but the actual seeking hasn't been done yet.

seekPosback to summary
private long seekPos

Target position for seeking.

streamsback to summary
private final ArrayList<IndexDecoder> streams

List of IndexDecoders, one for each Stream in the file. The list is in reverse order: The first element is the last Stream in the file.

tempBufback to summary
private final byte[] tempBuf

Temporary buffer for read(). This avoids reallocating memory on every read() call.

uncompressedSizeback to summary
private long uncompressedSize

Uncompressed size of the file (all Streams).

verifyCheckback to summary
private final boolean verifyCheck

Flag indicating if the integrity checks will be verified.

Constructor Detail

SeekableXZInputStreamback to summary
public SeekableXZInputStream(SeekableInputStream in) throws IOException

Creates a new seekable XZ decompressor without a memory usage limit.

Parameters
in:SeekableInputStream

seekable input stream containing one or more XZ Streams; the whole input stream is used

Exceptions
IOException:
may be thrown by in
XZFormatException:
input is not in the XZ format
CorruptedInputException:
XZ data is corrupt or truncated
UnsupportedOptionsException:
XZ headers seem valid but they specify options not supported by this implementation
EOFException:
less than 6 bytes of input was available from in, or (unlikely) the size of the underlying stream got smaller while this was reading from it
SeekableXZInputStreamback to summary
public SeekableXZInputStream(SeekableInputStream in, ArrayCache arrayCache) throws IOException

Creates a new seekable XZ decompressor without a memory usage limit.

This is identical to SeekableXZInputStream(SeekableInputStream) except that this also takes the arrayCache argument.

Parameters
in:SeekableInputStream

seekable input stream containing one or more XZ Streams; the whole input stream is used

arrayCache:ArrayCache

cache to be used for allocating large arrays

Exceptions
IOException:
may be thrown by in
XZFormatException:
input is not in the XZ format
CorruptedInputException:
XZ data is corrupt or truncated
UnsupportedOptionsException:
XZ headers seem valid but they specify options not supported by this implementation
EOFException:
less than 6 bytes of input was available from in, or (unlikely) the size of the underlying stream got smaller while this was reading from it
Since
1.7
SeekableXZInputStreamback to summary
public SeekableXZInputStream(SeekableInputStream in, int memoryLimit) throws IOException

Creates a new seekable XZ decomporessor with an optional memory usage limit.

Parameters
in:SeekableInputStream

seekable input stream containing one or more XZ Streams; the whole input stream is used

memoryLimit:int

memory usage limit in kibibytes (KiB) or -1 to impose no memory usage limit

Exceptions
IOException:
may be thrown by in
XZFormatException:
input is not in the XZ format
CorruptedInputException:
XZ data is corrupt or truncated
UnsupportedOptionsException:
XZ headers seem valid but they specify options not supported by this implementation
MemoryLimitException:
decoded XZ Indexes would need more memory than allowed by the memory usage limit
EOFException:
less than 6 bytes of input was available from in, or (unlikely) the size of the underlying stream got smaller while this was reading from it
SeekableXZInputStreamback to summary
public SeekableXZInputStream(SeekableInputStream in, int memoryLimit, ArrayCache arrayCache) throws IOException

Creates a new seekable XZ decomporessor with an optional memory usage limit.

This is identical to SeekableXZInputStream(SeekableInputStream,int) except that this also takes the arrayCache argument.

Parameters
in:SeekableInputStream

seekable input stream containing one or more XZ Streams; the whole input stream is used

memoryLimit:int

memory usage limit in kibibytes (KiB) or -1 to impose no memory usage limit

arrayCache:ArrayCache

cache to be used for allocating large arrays

Exceptions
IOException:
may be thrown by in
XZFormatException:
input is not in the XZ format
CorruptedInputException:
XZ data is corrupt or truncated
UnsupportedOptionsException:
XZ headers seem valid but they specify options not supported by this implementation
MemoryLimitException:
decoded XZ Indexes would need more memory than allowed by the memory usage limit
EOFException:
less than 6 bytes of input was available from in, or (unlikely) the size of the underlying stream got smaller while this was reading from it
Since
1.7
SeekableXZInputStreamback to summary
public SeekableXZInputStream(SeekableInputStream in, int memoryLimit, boolean verifyCheck) throws IOException

Creates a new seekable XZ decomporessor with an optional memory usage limit and ability to disable verification of integrity checks.

Note that integrity check verification should almost never be disabled. Possible reasons to disable integrity check verification:

  • Trying to recover data from a corrupt .xz file.
  • Speeding up decompression. This matters mostly with SHA-256 or with files that have compressed extremely well. It's recommended that integrity checking isn't disabled for performance reasons unless the file integrity is verified externally in some other way.

verifyCheck only affects the integrity check of the actual compressed data. The CRC32 fields in the headers are always verified.

Parameters
in:SeekableInputStream

seekable input stream containing one or more XZ Streams; the whole input stream is used

memoryLimit:int

memory usage limit in kibibytes (KiB) or -1 to impose no memory usage limit

verifyCheck:boolean

if true, the integrity checks will be verified; this should almost never be set to false

Exceptions
IOException:
may be thrown by in
XZFormatException:
input is not in the XZ format
CorruptedInputException:
XZ data is corrupt or truncated
UnsupportedOptionsException:
XZ headers seem valid but they specify options not supported by this implementation
MemoryLimitException:
decoded XZ Indexes would need more memory than allowed by the memory usage limit
EOFException:
less than 6 bytes of input was available from in, or (unlikely) the size of the underlying stream got smaller while this was reading from it
Since
1.6
SeekableXZInputStreamback to summary
public SeekableXZInputStream(SeekableInputStream in, int memoryLimit, boolean verifyCheck, ArrayCache arrayCache) throws IOException

Creates a new seekable XZ decomporessor with an optional memory usage limit and ability to disable verification of integrity checks.

This is identical to SeekableXZInputStream(SeekableInputStream,int,boolean) except that this also takes the arrayCache argument.

Parameters
in:SeekableInputStream

seekable input stream containing one or more XZ Streams; the whole input stream is used

memoryLimit:int

memory usage limit in kibibytes (KiB) or -1 to impose no memory usage limit

verifyCheck:boolean

if true, the integrity checks will be verified; this should almost never be set to false

arrayCache:ArrayCache

cache to be used for allocating large arrays

Exceptions
IOException:
may be thrown by in
XZFormatException:
input is not in the XZ format
CorruptedInputException:
XZ data is corrupt or truncated
UnsupportedOptionsException:
XZ headers seem valid but they specify options not supported by this implementation
MemoryLimitException:
decoded XZ Indexes would need more memory than allowed by the memory usage limit
EOFException:
less than 6 bytes of input was available from in, or (unlikely) the size of the underlying stream got smaller while this was reading from it
Since
1.7

Method Detail

availableback to summary
public int available() throws IOException

Overrides java.io.InputStream.available.

Returns the number of uncompressed bytes that can be read without blocking. The value is returned with an assumption that the compressed input data will be valid. If the compressed data is corrupt, CorruptedInputException may get thrown before the number of bytes claimed to be available have been read from this input stream.

Returns:int

the number of uncompressed bytes that can be read without blocking

Exceptions
IOException:

Doc from java.io.InputStream.available.

if an I/O error occurs.

closeback to summary
public void close() throws IOException

Overrides java.io.InputStream.close.

Implements java.io.Closeable.close.

Closes the stream and calls in.close(). If the stream was already closed, this does nothing.

This is equivalent to close(true).

Exceptions
IOException:
if thrown by in.close()
closeback to summary
public void close(boolean closeInput) throws IOException

Closes the stream and optionally calls in.close(). If the stream was already closed, this does nothing. If close(false) has been called, a further call of close(true) does nothing (it doesn't call in.close()).

If you don't want to close the underlying InputStream, there is usually no need to worry about closing this stream either; it's fine to do nothing and let the garbage collector handle it. However, if you are using ArrayCache, close(false) can be useful to put the allocated arrays back to the cache without closing the underlying InputStream.

Note that if you successfully reach the end of the stream (read returns -1), the arrays are automatically put back to the cache by that read call. In this situation close(false) is redundant (but harmless).

Exceptions
IOException:
if thrown by in.close()
Since
1.7
getBlockCheckTypeback to summary
public int getBlockCheckType(int blockNumber)

Gets integrity check type (Check ID) of the given Block.

Exceptions
IndexOutOfBoundsException:
if blockNumber < 0 or blockNumber >= getBlockCount().
Since
1.3
See Also
getCheckTypes()
getBlockCompPosback to summary
public long getBlockCompPos(int blockNumber)

Gets the position where the given compressed Block starts in the underlying .xz file. This information is rarely useful to the users of this class.

Exceptions
IndexOutOfBoundsException:
if blockNumber < 0 or blockNumber >= getBlockCount().
Since
1.3
getBlockCompSizeback to summary
public long getBlockCompSize(int blockNumber)

Gets the compressed size of the given Block. This together with the uncompressed size can be used to calculate the compression ratio of the specific Block.

Exceptions
IndexOutOfBoundsException:
if blockNumber < 0 or blockNumber >= getBlockCount().
Since
1.3
getBlockCountback to summary
public int getBlockCount()

Gets the number of Blocks in the .xz file.

Since
1.3
getBlockNumberback to summary
public int getBlockNumber(long pos)

Gets the number of the Block that contains the byte at the given uncompressed position.

Exceptions
IndexOutOfBoundsException:
if pos < 0 or pos >= length().
Since
1.3
getBlockPosback to summary
public long getBlockPos(int blockNumber)

Gets the uncompressed start position of the given Block.

Exceptions
IndexOutOfBoundsException:
if blockNumber < 0 or blockNumber >= getBlockCount().
Since
1.3
getBlockSizeback to summary
public long getBlockSize(int blockNumber)

Gets the uncompressed size of the given Block.

Exceptions
IndexOutOfBoundsException:
if blockNumber < 0 or blockNumber >= getBlockCount().
Since
1.3
getCheckTypesback to summary
public int getCheckTypes()

Gets the types of integrity checks used in the .xz file. Multiple checks are possible only if there are multiple concatenated XZ Streams.

The returned value has a bit set for every check type that is present. For example, if CRC64 and SHA-256 were used, the return value is (1 << XZ.CHECK_CRC64) | (1 << XZ.CHECK_SHA256).

getIndexMemoryUsageback to summary
public int getIndexMemoryUsage()

Gets the amount of memory in kibibytes (KiB) used by the data structures needed to locate the XZ Blocks. This is usually useless information but since it is calculated for memory usage limit anyway, it is nice to make it available to too.

getLargestBlockSizeback to summary
public long getLargestBlockSize()

Gets the uncompressed size of the largest XZ Block in bytes. This can be useful if you want to check that the file doesn't have huge XZ Blocks which could make seeking to arbitrary offsets very slow. Note that huge Blocks don't automatically mean that seeking would be slow, for example, seeking to the beginning of any Block is always fast.

getStreamCountback to summary
public int getStreamCount()

Gets the number of Streams in the .xz file.

Since
1.3
initBlockDecoderback to summary
private void initBlockDecoder() throws IOException

Initializes a new BlockInputStream. This is a helper function for seek().

lengthback to summary
public long length()

Implements abstract org.tukaani.xz.SeekableInputStream.length.

Gets the uncompressed size of this input stream. If there are multiple XZ Streams, the total uncompressed size of all XZ Streams is returned.

locateBlockByNumberback to summary
private void locateBlockByNumber(BlockInfo info, int blockNumber)

Locates the given Block and stores information about it to info.

locateBlockByPosback to summary
private void locateBlockByPos(BlockInfo info, long pos)

Locates the Block that contains the given uncompressed position.

positionback to summary
public long position() throws IOException

Implements abstract org.tukaani.xz.SeekableInputStream.position.

Gets the current uncompressed position in this input stream.

Exceptions
XZIOException:
if the stream has been closed
readback to summary
public int read() throws IOException

Implements abstract java.io.InputStream.read.

Decompresses the next byte from this input stream.

Returns:int

the next decompressed byte, or -1 to indicate the end of the compressed stream

Exceptions
IOException:
may be thrown by in
XZIOException:
if the stream has been closed
readback to summary
public int read(byte[] buf, int off, int len) throws IOException

Overrides java.io.InputStream.read.

Decompresses into an array of bytes.

If len is zero, no bytes are read and 0 is returned. Otherwise this will try to decompress len bytes of uncompressed data. Less than len bytes may be read only in the following situations:

  • The end of the compressed data was reached successfully.
  • An error is detected after at least one but less than len bytes have already been successfully decompressed. The next call with non-zero len will immediately throw the pending exception.
  • An exception is thrown.
Parameters
buf:byte[]

target buffer for uncompressed data

off:int

start offset in buf

len:int

maximum number of uncompressed bytes to read

Returns:int

number of bytes read, or -1 to indicate the end of the compressed stream

Exceptions
IOException:
may be thrown by in
XZIOException:
if the stream has been closed
seekback to summary
public void seek(long pos) throws IOException

Implements abstract org.tukaani.xz.SeekableInputStream.seek.

Seeks to the specified absolute uncompressed position in the stream. This only stores the new position, so this function itself is always very fast. The actual seek is done when read is called to read at least one byte.

Seeking past the end of the stream is possible. In that case read will return -1 to indicate the end of the stream.

Parameters
pos:long

new uncompressed read position

Exceptions
IOException:

Doc from org.tukaani.xz.SeekableInputStream.seek.

if pos is negative or if a stream-specific I/O error occurs

XZIOException:
if pos is negative, or if stream has been closed
seekback to summary
private void seek() throws IOException

Does the actual seeking. This is also called when read needs a new Block to decode.

seekToBlockback to summary
public void seekToBlock(int blockNumber) throws IOException

Seeks to the beginning of the given XZ Block.

Exceptions
XZIOException:
if blockNumber < 0 or blockNumber >= getBlockCount(), or if stream has been closed
Since
1.3