class Zlib::GzipReader
Zlib::GzipReader
是用于读取 gzip 文件的类。GzipReader
应该被用作 IO
或类 IO 的对象。
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
目录¶ ↑
Zlib::GzipReader
中的以下方法与 IO
中的对应方法类似,但是如果在 gzip 文件中发现错误,它们会抛出 Zlib::Error
或 Zlib::GzipFile::Error
异常。
请注意 gzip 文件的页脚。gzip 文件在其页脚中包含预压缩数据的校验和。GzipReader
会在以下情况下针对该校验和检查所有未压缩的数据,如果检查失败,则会抛出 Zlib::GzipFile::NoFooter
、Zlib::GzipFile::CRCError
或 Zlib::GzipFile::LengthError
异常。
-
当收到超出文件末尾(压缩数据末尾)的读取请求时。也就是说,当
Zlib::GzipReader#read
、Zlib::GzipReader#gets
或其他一些读取方法返回 nil 时。 -
当对象到达文件末尾后调用
Zlib::GzipFile#close
方法时。 -
当对象到达文件末尾后调用
Zlib::GzipReader#unused
方法时。
其余方法在其各自的文档中有充分的描述。
公共类方法
源代码
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; }
创建一个与 io
关联的 GzipReader
对象。GzipReader
对象从 io
读取 gzip 压缩的数据,并解析/解压它。io
必须有一个 read
方法,其行为与 IO#read
相同。
可以使用 options
哈希设置数据的编码。可以像在 IO::new
中一样设置 :external_encoding
、:internal_encoding
和 :encoding
。
如果 gzip 文件头不正确,则会抛出 Zlib::GzipFile::Error
异常。
源代码
static VALUE rb_gzreader_s_open(int argc, VALUE *argv, VALUE klass) { return gzfile_s_open(argc, argv, klass, "rb"); }
以 gzip 文件的形式打开由 filename
指定的文件,并返回一个与该文件关联的 GzipReader
对象。有关此方法的更多详细信息,请参见 Zlib::GzipReader.new
和 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; }
解压缩 io
中的所有 gzip 数据,处理多个 gzip 流,直到 io
的末尾。gzip 流之后不应有任何非 gzip 数据。
如果给定了块,则会向其产生未压缩的数据字符串,并且该方法返回 nil
。如果没有给出块,则该方法返回所有 gzip 流中所有未压缩数据的连接。
公共实例方法
源代码
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; }
有关描述,请参阅 Zlib::GzipReader
文档。
源代码
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; }
有关描述,请参阅 Zlib::GzipReader
文档。
源代码
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; }
有关描述,请参阅 Zlib::GzipReader
文档。
源代码
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; }
返回 true
或 false
,表示流是否已到达末尾。
源代码
static VALUE rb_gzreader_external_encoding(VALUE self) { return rb_enc_from_encoding(get_gzfile(self)->enc); }
有关描述,请参阅 Zlib::GzipReader
文档。
源代码
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; }
有关描述,请参阅 Zlib::GzipReader
文档。
源代码
static VALUE rb_gzreader_getc(VALUE obj) { struct gzfile *gz = get_gzfile(obj); return gzfile_getc(gz); }
有关描述,请参阅 Zlib::GzipReader
文档。
源代码
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; }
有关描述,请参阅 Zlib::GzipReader
文档。但是,请注意,即使 eof?
返回 false,此方法也可能返回 nil
,这与 File#gets
的行为不同。
源代码
static VALUE rb_gzfile_lineno(VALUE obj) { return INT2NUM(get_gzfile(obj)->lineno); }
从此文件读取的最后一行的行号。
源代码
static VALUE rb_gzfile_set_lineno(VALUE obj, VALUE lineno) { struct gzfile *gz = get_gzfile(obj); gz->lineno = NUM2INT(lineno); return lineno; }
指定从此文件读取的最后一行的行号。
源代码
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)); } }
到目前为止输出的总输出字节数。
源代码
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); }
有关描述,请参阅 Zlib::GzipReader
文档。
源代码
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; }
有关描述,请参阅 Zlib::GzipReader
文档。
源代码
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; }
有关描述,请参阅 Zlib::GzipReader
文档。
源代码
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; }
有关描述,请参阅 Zlib::GzipReader
文档。
源代码
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; }
有关描述,请参阅 Zlib::GzipReader
文档。
源代码
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); }
最多从 gzip 流读取 maxlen 个字节,但只有当 gzipreader 没有立即可用的数据时才会阻塞。如果存在可选的 outbuf 参数,则它必须引用一个 String
,该字符串将接收数据。它会在文件末尾引发 EOFError
。
源代码
static VALUE rb_gzreader_rewind(VALUE obj) { struct gzfile *gz = get_gzfile(obj); gzfile_reader_rewind(gz); return INT2FIX(0); }
将文件指针的位置重置为创建 GzipReader
对象时的位置。关联的 IO
对象需要响应 seek
方法。
源代码
static VALUE rb_gzreader_ungetbyte(VALUE obj, VALUE ch) { struct gzfile *gz = get_gzfile(obj); gzfile_ungetbyte(gz, NUM2CHR(ch)); return Qnil; }
有关描述,请参阅 Zlib::GzipReader
文档。
源代码
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; }
有关描述,请参阅 Zlib::GzipReader
文档。
源代码
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); }
返回为解析 gzip 格式而读取的其余数据,如果尚未解析整个 gzip 文件,则返回 nil
。