类 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::ErrorZlib::GzipFile::Error 异常。

注意 gzip 文件的页脚。gzip 文件在其页脚中包含预压缩数据的校验和。 GzipReader 在以下情况下会检查所有未压缩数据与该校验和是否匹配,如果失败,则会引发 Zlib::GzipFile::NoFooterZlib::GzipFile::CRCErrorZlib::GzipFile::LengthError 异常。

其他方法在其自己的文档中进行了充分的描述。

公共类方法

Zlib::GzipReader.new(io, options = {}) 点击切换源代码

创建一个与 io 关联的 GzipReader 对象。 GzipReader 对象从 io 读取 gzip 数据,并对其进行解析/解压缩。io 必须具有一个 read 方法,其行为与 IO#read 相同。

可以使用 options 哈希设置数据的编码。:external_encoding:internal_encoding:encoding 可以像在 IO::new 中一样设置。

如果 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;
}
Zlib::GzipReader.open(filename) {|gz| ... } 点击切换源代码

filename 指定的文件打开为 gzip 文件,并返回与该文件关联的 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");
}
Zlib::GzipReader.zcat(io, options = {}, &block) → nil 点击切换源代码
Zlib::GzipReader.zcat(io, options = {}) → string

解压缩 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));
            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;
}

公共实例方法

each(*args) 点击切换源代码

有关描述,请参见 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;
}
也称为:each_line
each_byte() 点击切换源代码

有关描述,请参见 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;
}
each_char() 点击切换源代码

有关描述,请参见 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;
}
each_line(*args)

有关描述,请参见 Zlib::GzipReader 文档。

别名:each
eof() 点击切换源代码

返回 truefalse,表示流是否已到达末尾。

static VALUE
rb_gzfile_eof_p(VALUE obj)
{
    struct gzfile *gz = get_gzfile(obj);
    return GZFILE_IS_FINISHED(gz) ? Qtrue : Qfalse;
}
也称为:eof?
eof?()

返回 truefalse,表示流是否已到达末尾。

别名:eof
external_encoding() 点击切换源代码

有关描述,请参见 Zlib::GzipReader 文档。

static VALUE
rb_gzreader_external_encoding(VALUE self)
{
    return rb_enc_from_encoding(get_gzfile(self)->enc);
}
getbyte() 点击切换源代码

有关描述,请参见 Zlib::GzipReader 文档。

static VALUE
rb_gzreader_getbyte(VALUE obj)
{
    struct gzfile *gz = get_gzfile(obj);
    VALUE dst;

    dst = gzfile_read(gz, 1);
    if (!NIL_P(dst)) {
        dst = INT2FIX((unsigned int)(RSTRING_PTR(dst)[0]) & 0xff);
    }
    return dst;
}
getc() 点击切换源代码

有关描述,请参见 Zlib::GzipReader 文档。

static VALUE
rb_gzreader_getc(VALUE obj)
{
    struct gzfile *gz = get_gzfile(obj);

    return gzfile_getc(gz);
}
gets(*args) 点击切换源代码

有关描述,请参阅 Zlib::GzipReader 文档。但是,请注意,与 File#gets 的行为不同,即使 eof? 返回 false,此方法也可能返回 nil

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;
}
lineno() 点击切换源代码

从该文件读取的最后一行行号。

static VALUE
rb_gzfile_lineno(VALUE obj)
{
    return INT2NUM(get_gzfile(obj)->lineno);
}
lineno=(p1) 点击切换源代码

指定从该文件读取的最后一行行号。

static VALUE
rb_gzfile_set_lineno(VALUE obj, VALUE lineno)
{
    struct gzfile *gz = get_gzfile(obj);
    gz->lineno = NUM2INT(lineno);
    return lineno;
}
pos() 点击切换源代码

到目前为止输出的总字节数。

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));
    }
}
也称为:tell
read(p1 = v1) 点击切换源代码

有关描述,请参见 Zlib::GzipReader 文档。

static VALUE
rb_gzreader_read(int argc, VALUE *argv, VALUE obj)
{
    struct gzfile *gz = get_gzfile(obj);
    VALUE vlen;
    long len;

    rb_scan_args(argc, argv, "01", &vlen);
    if (NIL_P(vlen)) {
        return gzfile_read_all(gz);
    }

    len = NUM2INT(vlen);
    if (len < 0) {
        rb_raise(rb_eArgError, "negative length %ld given", len);
    }
    return gzfile_read(gz, len);
}
readbyte() 点击切换源代码

有关描述,请参见 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;
}
readchar() 点击切换源代码

有关描述,请参见 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;
}
readline(*args) 点击切换源代码

有关描述,请参见 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;
}
readlines(*args) 点击切换源代码

有关描述,请参见 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;
}
readpartial(maxlen [, outbuf]) → string, outbuf 点击切换源代码

从 gziped 流中读取最多 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);
}
rewind() 点击切换源代码

将文件指针的位置重置为创建 GzipReader 对象的点。关联的 IO 对象需要响应 seek 方法。

static VALUE
rb_gzreader_rewind(VALUE obj)
{
    struct gzfile *gz = get_gzfile(obj);
    gzfile_reader_rewind(gz);
    return INT2FIX(0);
}
tell()

到目前为止输出的总字节数。

别名:pos
ungetbyte(p1) 点击切换源代码

有关描述,请参见 Zlib::GzipReader 文档。

static VALUE
rb_gzreader_ungetbyte(VALUE obj, VALUE ch)
{
    struct gzfile *gz = get_gzfile(obj);
    gzfile_ungetbyte(gz, NUM2CHR(ch));
    return Qnil;
}
ungetc(p1) 点击切换源代码

有关描述,请参见 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;
}
unused() 点击切换源代码

返回用于解析 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);
}