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
方法目录¶ ↑
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
方法时。
其余方法在其各自的文档中有充分描述。
公共类方法
创建一个与 io
关联的 GzipReader
对象。GzipReader
对象从 io
读取 gzip 数据,并解析/解压缩它。io
必须具有一个行为与 IO#read 相同的 read
方法。
可以使用 options
哈希来设置数据的编码。可以像在 IO::new 中一样设置 :external_encoding
、:internal_encoding
和 :encoding
。
如果 gzip 文件头不正确,则会引发 Zlib::GzipFile::Error
异常。
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; }
以 gzip 文件形式打开由 filename
指定的文件,并返回与该文件关联的 GzipReader
对象。此方法的更多详细信息请参阅 Zlib::GzipReader.new
和 ZLib::GzipFile.wrap。
static VALUE rb_gzreader_s_open(int argc, VALUE *argv, VALUE klass) { return gzfile_s_open(argc, argv, klass, "rb"); }
解压缩 io
中的所有 gzip 数据,处理多个 gzip 流直到 io
的末尾。gzip 流之后不应有任何非 gzip 数据。
如果给定了代码块,则会将未压缩数据的字符串传递给代码块,并且该方法返回 nil
。如果没有给定代码块,则该方法将返回所有 gzip 流中所有未压缩数据的连接。
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; }
公共实例方法
有关描述,请参阅 Zlib::GzipReader
文档。
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; }
返回 true
或 false
,表示流是否已到达末尾。
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; }
有关描述,请参阅 Zlib::GzipReader
文档。
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
文档。但是请注意,即使 eof?
返回 false,此方法也可能返回 nil
,这与 File#gets 的行为不同。
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; }
从该文件读取的最后一行所在的行号。
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)); } }
有关描述,请参阅 Zlib::GzipReader
文档。
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; }
从 gzip 流中读取最多 maxlen 个字节,但只有在 gzipreader 没有立即可用的数据时才会阻塞。如果存在可选的 outbuf 参数,则它必须引用一个将接收数据的 String。它在文件末尾引发 EOFError
。
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); }
将文件指针的位置重置为创建 GzipReader
对象时所处的位置。关联的 IO 对象需要响应 seek
方法。
static VALUE rb_gzreader_rewind(VALUE obj) { struct gzfile *gz = get_gzfile(obj); gzfile_reader_rewind(gz); return INT2FIX(0); }
有关描述,请参阅 Zlib::GzipReader
文档。
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; }
返回为解析 gzip 格式而读取的其余数据,如果尚未解析整个 gzip 文件,则返回 nil
。
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); }