Zlib::GzipReader
is the class for reading a gzipped file. GzipReader
should be used as an IO
, or -IO-like, object.
Zlib::GzipReader.open('hoge.gz') {|gz| print gz.read } File.open('hoge.gz') do |f| gz = Zlib::GzipReader.new(f) print gz.read gz.close end
Method
Catalogue
The following methods in Zlib::GzipReader
are just like their counterparts in IO
, but they raise Zlib::Error
or Zlib::GzipFile::Error
exception if an error was found in the gzip file.
Be careful of the footer of the gzip file. A gzip file has the checksum of pre-compressed data in its footer. GzipReader
checks all uncompressed data against that checksum at the following cases, and if it fails, raises Zlib::GzipFile::NoFooter
, Zlib::GzipFile::CRCError
, or Zlib::GzipFile::LengthError
exception.
-
When an reading request is received beyond the end of file (the end of compressed data). That is, when
Zlib::GzipReader#read
,Zlib::GzipReader#gets
, or some other methods for reading returns nil. -
When
Zlib::GzipFile#close
method is called after the object reaches the end of file. -
When
Zlib::GzipReader#unused
method is called after the object reaches the end of file.
The rest of the methods are adequately described in their own documentation.
static VALUE
rb_gzreader_initialize(int argc, VALUE *argv, VALUE obj)
{
VALUE io, opt = Qnil;
struct gzfile *gz;
int err;
TypedData_Get_Struct(obj, struct gzfile, &gzfile_data_type, gz);
rb_scan_args(argc, argv, "1:", &io, &opt);
/* this is undocumented feature of zlib */
err = inflateInit2(&gz->z.stream, -MAX_WBITS);
if (err != Z_OK) {
raise_zlib_error(err, gz->z.stream.msg);
}
gz->io = io;
ZSTREAM_READY(&gz->z);
gzfile_read_header(gz, Qnil);
rb_gzfile_ecopts(gz, opt);
if (rb_respond_to(io, id_path)) {
/* File#path may raise IOError in case when a path is unavailable */
rb_rescue2(gzfile_initialize_path_partial, obj, NULL, Qnil, rb_eIOError, (VALUE)0);
}
return obj;
}
Creates a GzipReader
object associated with io
. The GzipReader
object reads gzipped data from io
, and parses/decompresses it. The io
must have a read
method that behaves same as the IO#read
.
The options
hash may be used to set the encoding of the data. :external_encoding
, :internal_encoding
and :encoding
may be set as in IO::new
.
If the gzip file header is incorrect, raises an Zlib::GzipFile::Error
exception.
static VALUE
rb_gzreader_s_open(int argc, VALUE *argv, VALUE klass)
{
return gzfile_s_open(argc, argv, klass, "rb");
}
Opens a file specified by filename
as a gzipped file, and returns a GzipReader
object associated with that file. Further details of this method are in Zlib::GzipReader.new
and ZLib::GzipFile.wrap.
static VALUE
rb_gzreader_s_zcat(int argc, VALUE *argv, VALUE klass)
{
VALUE io, unused, obj, buf=0, tmpbuf;
long pos;
rb_check_arity(argc, 1, 2);
io = argv[0];
do {
obj = rb_funcallv(klass, rb_intern("new"), argc, argv);
if (rb_block_given_p()) {
rb_gzreader_each(0, 0, obj);
}
else {
if (!buf) {
buf = rb_str_new(0, 0);
}
tmpbuf = gzfile_read_all(get_gzfile(obj), Qnil);
rb_str_cat(buf, RSTRING_PTR(tmpbuf), RSTRING_LEN(tmpbuf));
}
rb_gzreader_read(0, 0, obj);
pos = NUM2LONG(rb_funcall(io, rb_intern("pos"), 0));
unused = rb_gzreader_unused(obj);
rb_gzfile_finish(obj);
if (!NIL_P(unused)) {
pos -= NUM2LONG(rb_funcall(unused, rb_intern("length"), 0));
rb_funcall(io, rb_intern("pos="), 1, LONG2NUM(pos));
}
} while (pos < NUM2LONG(rb_funcall(io, rb_intern("size"), 0)));
if (rb_block_given_p()) {
return Qnil;
}
return buf;
}
Decompresses all gzip data in the io
, handling multiple gzip streams until the end of the io
. There should not be any non-gzip data after the gzip streams.
If a block is given, it is yielded strings of uncompressed data, and the method returns nil
. If a block is not given, the method returns the concatenation of all uncompressed data in all gzip streams.
static VALUE
rb_gzreader_each(int argc, VALUE *argv, VALUE obj)
{
VALUE str;
RETURN_ENUMERATOR(obj, 0, 0);
while (!NIL_P(str = gzreader_gets(argc, argv, obj))) {
rb_yield(str);
}
return obj;
}
See Zlib::GzipReader
documentation for a description.
static VALUE
rb_gzreader_each_byte(VALUE obj)
{
VALUE c;
RETURN_ENUMERATOR(obj, 0, 0);
while (!NIL_P(c = rb_gzreader_getbyte(obj))) {
rb_yield(c);
}
return Qnil;
}
See Zlib::GzipReader
documentation for a description.
static VALUE
rb_gzreader_each_char(VALUE obj)
{
VALUE c;
RETURN_ENUMERATOR(obj, 0, 0);
while (!NIL_P(c = rb_gzreader_getc(obj))) {
rb_yield(c);
}
return Qnil;
}
See Zlib::GzipReader
documentation for a description.
static VALUE
rb_gzfile_eof_p(VALUE obj)
{
struct gzfile *gz = get_gzfile(obj);
while (!ZSTREAM_IS_FINISHED(&gz->z) && ZSTREAM_BUF_FILLED(&gz->z) == 0) {
gzfile_read_more(gz, Qnil);
}
return GZFILE_IS_FINISHED(gz) ? Qtrue : Qfalse;
}
Returns true
or false
whether the stream has reached the end.
static VALUE
rb_gzreader_external_encoding(VALUE self)
{
return rb_enc_from_encoding(get_gzfile(self)->enc);
}
See Zlib::GzipReader
documentation for a description.
static VALUE
rb_gzreader_getbyte(VALUE obj)
{
struct gzfile *gz = get_gzfile(obj);
VALUE dst;
dst = gzfile_read(gz, 1, Qnil);
if (!NIL_P(dst)) {
dst = INT2FIX((unsigned int)(RSTRING_PTR(dst)[0]) & 0xff);
}
return dst;
}
See Zlib::GzipReader
documentation for a description.
static VALUE
rb_gzreader_getc(VALUE obj)
{
struct gzfile *gz = get_gzfile(obj);
return gzfile_getc(gz);
}
See Zlib::GzipReader
documentation for a description.
static VALUE
rb_gzreader_gets(int argc, VALUE *argv, VALUE obj)
{
VALUE dst;
dst = gzreader_gets(argc, argv, obj);
if (!NIL_P(dst)) {
rb_lastline_set(dst);
}
return dst;
}
See Zlib::GzipReader
documentation for a description. However, note that this method can return nil
even if eof?
returns false, unlike the behavior of File#gets
.
static VALUE
rb_gzfile_lineno(VALUE obj)
{
return INT2NUM(get_gzfile(obj)->lineno);
}
The line number of the last row read from this file.
static VALUE
rb_gzfile_set_lineno(VALUE obj, VALUE lineno)
{
struct gzfile *gz = get_gzfile(obj);
gz->lineno = NUM2INT(lineno);
return lineno;
}
Specify line number of the last row read from this file.
static VALUE
rb_gzfile_total_out(VALUE obj)
{
struct gzfile *gz = get_gzfile(obj);
uLong total_out = gz->z.stream.total_out;
long buf_filled = ZSTREAM_BUF_FILLED(&gz->z);
if (total_out >= (uLong)buf_filled) {
return rb_uint2inum(total_out - buf_filled);
} else {
return LONG2FIX(-(buf_filled - (long)total_out));
}
}
Total number of output bytes output so far.
static VALUE
rb_gzreader_read(int argc, VALUE *argv, VALUE obj)
{
struct gzfile *gz = get_gzfile(obj);
VALUE vlen, outbuf;
long len;
rb_scan_args(argc, argv, "02", &vlen, &outbuf);
if (NIL_P(vlen)) {
return gzfile_read_all(gz, outbuf);
}
len = NUM2INT(vlen);
if (len < 0) {
rb_raise(rb_eArgError, "negative length %ld given", len);
}
return gzfile_read(gz, len, outbuf);
}
See Zlib::GzipReader
documentation for a description.
static VALUE
rb_gzreader_readbyte(VALUE obj)
{
VALUE dst;
dst = rb_gzreader_getbyte(obj);
if (NIL_P(dst)) {
rb_raise(rb_eEOFError, "end of file reached");
}
return dst;
}
See Zlib::GzipReader
documentation for a description.
static VALUE
rb_gzreader_readchar(VALUE obj)
{
VALUE dst;
dst = rb_gzreader_getc(obj);
if (NIL_P(dst)) {
rb_raise(rb_eEOFError, "end of file reached");
}
return dst;
}
See Zlib::GzipReader
documentation for a description.
static VALUE
rb_gzreader_readline(int argc, VALUE *argv, VALUE obj)
{
VALUE dst;
dst = rb_gzreader_gets(argc, argv, obj);
if (NIL_P(dst)) {
rb_raise(rb_eEOFError, "end of file reached");
}
return dst;
}
See Zlib::GzipReader
documentation for a description.
static VALUE
rb_gzreader_readlines(int argc, VALUE *argv, VALUE obj)
{
VALUE str, dst;
dst = rb_ary_new();
while (!NIL_P(str = gzreader_gets(argc, argv, obj))) {
rb_ary_push(dst, str);
}
return dst;
}
See Zlib::GzipReader
documentation for a description.
static VALUE
rb_gzreader_readpartial(int argc, VALUE *argv, VALUE obj)
{
struct gzfile *gz = get_gzfile(obj);
VALUE vlen, outbuf;
long len;
rb_scan_args(argc, argv, "11", &vlen, &outbuf);
len = NUM2INT(vlen);
if (len < 0) {
rb_raise(rb_eArgError, "negative length %ld given", len);
}
if (!NIL_P(outbuf))
Check_Type(outbuf, T_STRING);
return gzfile_readpartial(gz, len, outbuf);
}
Reads at most maxlen bytes from the gziped stream but it blocks only if gzipreader has no data immediately available. If the optional outbuf argument is present, it must reference a String
, which will receive the data. It raises EOFError
on end of file.
static VALUE
rb_gzreader_rewind(VALUE obj)
{
struct gzfile *gz = get_gzfile(obj);
gzfile_reader_rewind(gz);
return INT2FIX(0);
}
Resets the position of the file pointer to the point created the GzipReader
object. The associated IO
object needs to respond to the seek
method.
static VALUE
rb_gzreader_ungetbyte(VALUE obj, VALUE ch)
{
struct gzfile *gz = get_gzfile(obj);
gzfile_ungetbyte(gz, NUM2CHR(ch));
return Qnil;
}
See Zlib::GzipReader
documentation for a description.
static VALUE
rb_gzreader_ungetc(VALUE obj, VALUE s)
{
struct gzfile *gz;
if (FIXNUM_P(s))
return rb_gzreader_ungetbyte(obj, s);
gz = get_gzfile(obj);
StringValue(s);
if (gz->enc2 && gz->enc2 != rb_ascii8bit_encoding()) {
s = rb_str_conv_enc(s, rb_enc_get(s), gz->enc2);
}
gzfile_ungets(gz, (const Bytef*)RSTRING_PTR(s), RSTRING_LEN(s));
RB_GC_GUARD(s);
return Qnil;
}
See Zlib::GzipReader
documentation for a description.
static VALUE
rb_gzreader_unused(VALUE obj)
{
struct gzfile *gz;
TypedData_Get_Struct(obj, struct gzfile, &gzfile_data_type, gz);
return gzfile_reader_get_unused(gz);
}
Returns the rest of the data which had read for parsing gzip format, or nil
if the whole gzip file is not parsed yet.