class Zlib::ZReader
Zlib::ZReader is a readable, IO-like object (includes IO::Like) which wraps other readable, IO-like objects in order to facilitate reading data from those objects using the inflate method of decompression.
Constants
- DEFAULT_DELEGATE_READ_SIZE
The number of bytes to read from the delegate object each time the internal read buffer is filled.
Attributes
The delegate object from which compressed data is read.
The number of bytes to read from the delegate object each time the internal read buffer is filled.
Public Class Methods
Creates a new instance of this class. delegate must respond to the read method as an IO instance would. window_bits is passed directly to Zlib::Inflate.new().
The following description of window_bits is based on the description found in zlib.h version 1.2.3. Some of the statements concerning default settings or value ranges may not be accurate depending on the version of the zlib library used by a given Ruby interpreter.
The window_bits parameter specifies the size of the history
buffer, the format of the compressed stream, and the kind of checksum
returned by the checksum method. The size of the history buffer is
specified by setting the value of window_bits in the range of
8
..15
, inclusive. It must be at least as large
as the setting used to create the stream or a Zlib::DataError will be
raised. Modification of this base value for window_bits as noted
below dictates what kind of compressed stream is expected and what kind of
checksum will be produced while preserving the setting for the
history buffer.
If nothing else is done to the base value of window_bits, a zlib stream is expected with an appropriate header and trailer. In this case the checksum method of this object will be an adler32.
Adding 16
to the base value of window_bits indicates
that a gzip stream is expected with an appropriate header and trailer. In
this case the checksum method of this object will be a crc32.
Adding 32
to the base value of window_bits indicates
that an automatic detection of the stream format should be made based on
the header in the stream. In this case the checksum method of this object
will depend on whether a zlib or a gzip stream is detected.
Finally, negating the base value of window_bits indicates that a
raw zlib stream is expected without any header or trailer. In this case
the checksum method of this object will always return nil
.
This is for use with other formats that use the deflate compressed data
format such as zip. Such formats should provide their own check values.
If unspecified or nil
, window_bits defaults to
15
.
In all cases, Zlib::DataError is raised if the wrong stream format is found when reading.
This class has extremely limited seek capabilities. It is possible to seek
with an offset of 0
and a whence of IO::SEEK_CUR
.
As a result, the pos and tell methods also work as
expected.
Due to certain optimizations within IO::Like#seek and if there is data in the read buffer, the seek method can be used to seek forward from the current stream position up to the end of the buffer. Unless it is known definitively how much data is in the buffer, it is best to avoid relying on this behavior.
If delegate also responds to rewind, then the
rewind method of this class can be used to reset the whole stream
back to the beginning. Using seek of this class to seek directly
to offset 0
using IO::SEEK_SET
for whence will
also work in this case.
Any other seeking attempts, will raise Errno::EINVAL exceptions.
NOTE: Due to limitations in Ruby's finalization capabilities, the close method is not automatically called when this object is garbage collected. Make sure to call close when finished with this object.
# File lib/archive/support/zlib.rb, line 347 def initialize(delegate, window_bits = nil) @delegate = delegate @delegate_read_size = DEFAULT_DELEGATE_READ_SIZE @window_bits = window_bits @inflater = Zlib::Inflate.new(@window_bits) @inflate_buffer = '' @checksum = nil @compressed_size = nil @uncompressed_size = nil end
Creates a new instance of this class with the given arguments using new and then passes the instance to the given block. The close method is guaranteed to be called after the block completes.
Equivalent to new if no block is given.
# File lib/archive/support/zlib.rb, line 271 def self.open(delegate, window_bits = nil) zr = new(delegate, window_bits) return zr unless block_given? begin yield(zr) ensure zr.close unless zr.closed? end end
Public Instance Methods
Returns the checksum computed over the data read from this stream.
NOTE: Refer to the documentation of new concerning window_bits to learn what kind of checksum will be returned.
NOTE: The contents of the internal read buffer are immediately processed any time the internal buffer is filled, so this checksum is only accurate if all data has been read out of this object.
# File lib/archive/support/zlib.rb, line 377 def checksum return nil if @window_bits < 0 @inflater.closed? ? @checksum : @inflater.adler end
Closes the reader.
Raises IOError if called more than once.
# File lib/archive/support/zlib.rb, line 385 def close super() @checksum = @inflater.adler @compressed_size = @inflater.total_in @uncompressed_size = @inflater.total_out @inflater.close nil end
Returns the number of bytes sent to be compressed so far.
NOTE: This value is updated whenever the internal read buffer needs to be filled, not when data is read out of this stream.
# File lib/archive/support/zlib.rb, line 398 def compressed_size @inflater.closed? ? @compressed_size : @inflater.total_in end
Returns the number of bytes of decompressed data produced so far.
NOTE: This value is updated whenever the internal read buffer needs to be filled, not when data is read out of this stream.
# File lib/archive/support/zlib.rb, line 406 def uncompressed_size @inflater.closed? ? @uncompressed_size : @inflater.total_out end
Private Instance Methods
# File lib/archive/support/zlib.rb, line 412 def unbuffered_read(length) if @inflate_buffer.empty? && @inflater.finished? then raise EOFError, 'end of file reached' end begin while @inflate_buffer.length < length && ! @inflater.finished? do @inflate_buffer << @inflater.inflate(delegate.read(@delegate_read_size)) end rescue Errno::EINTR, Errno::EAGAIN raise if @inflate_buffer.empty? end @inflate_buffer.slice!(0, length) end
Allows resetting this object and the delegate object back to the beginning of the stream or reporting the current position in the stream.
Raises Errno::EINVAL unless offset is 0
and
whence is either IO::SEEK_SET or IO::SEEK_CUR. Raises
Errno::EINVAL if whence is IO::SEEK_SEK and the delegate object
does not respond to the rewind method.
# File lib/archive/support/zlib.rb, line 435 def unbuffered_seek(offset, whence = IO::SEEK_SET) unless offset == 0 && ((whence == IO::SEEK_SET && delegate.respond_to?(:rewind)) || whence == IO::SEEK_CUR) then raise Errno::EINVAL end case whence when IO::SEEK_SET delegate.rewind @inflater.close @inflater = Zlib::Inflate.new(@window_bits) @inflate_buffer = '' 0 when IO::SEEK_CUR @inflater.total_out - @inflate_buffer.length end end