# class Zlib::GzipWriter

`Zlib::GzipWriter` is a class for writing gzipped files. `GzipWriter` should be used with an instance of `IO`, or IO-like, object.

Following two example generate the same result.

    Zlib::GzipWriter.open('hoge.gz') do |gz|
      gz.write 'jugemu jugemu gokou no surikire...'
    end

    File.open('hoge.gz', 'w') do |f|
      gz = Zlib::GzipWriter.new(f)
      gz.write 'jugemu jugemu gokou no surikire...'
      gz.close
    end

To make like gzip(1) does, run following:

    orig = 'hoge.txt'
    Zlib::GzipWriter.open('hoge.gz') do |gz|
      gz.mtime = File.mtime(orig)
      gz.orig_name = orig
      gz.write IO.binread(orig)
    end

NOTE: Due to the limitation of Ruby’s finalizer, you must explicitly close `GzipWriter` objects by `Zlib::GzipWriter#close` etc. Otherwise, `GzipWriter` will be not able to write the gzip footer and will generate a broken gzip file.

### Public Class Methods

Zlib::GzipWriter.new(io, level = nil, strategy = nil, options = {}) click to toggle source

Creates a `GzipWriter` object associated with `io`. `level` and `strategy` should be the same as the arguments of `Zlib::Deflate.new`. The `GzipWriter` object writes gzipped data to `io`. `io` must respond to the `write` method that behaves the same as `IO#write`.

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`.

    static VALUE
    rb_gzwriter_initialize(int argc, VALUE *argv, VALUE obj)
    {
        struct gzfile *gz;
        VALUE io, level, strategy, opt = Qnil;
        int err;

        if (argc > 1) {
            opt = rb_check_convert_type(argv[argc-1], T_HASH, "Hash", "to_hash");
            if (!NIL_P(opt)) argc--;
        }

        rb_scan_args(argc, argv, "12", &io, &level, &strategy);
        TypedData_Get_Struct(obj, struct gzfile, &gzfile_data_type, gz);

        /* this is undocumented feature of zlib */
        gz->level = ARG_LEVEL(level);
        err = deflateInit2(&gz->z.stream, gz->level, Z_DEFLATED,
                           -MAX_WBITS, DEF_MEM_LEVEL, ARG_STRATEGY(strategy));
        if (err != Z_OK) {
            raise_zlib_error(err, gz->z.stream.msg);
        }
        gz->io = io;
        ZSTREAM_READY(&gz->z);
        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::GzipWriter.open(filename, level=nil, strategy=nil) { |gz| ... } click to toggle source

Opens a file specified by `filename` for writing gzip compressed data, and returns a `GzipWriter` object associated with that file. Further details of this method are found in `Zlib::GzipWriter.new` and `Zlib::GzipFile.wrap`.

    static VALUE
    rb_gzwriter_s_open(int argc, VALUE *argv, VALUE klass)
    {
        return gzfile_s_open(argc, argv, klass, "wb");
    }

### Public Instance Methods

<<(p1) click to toggle source

Same as `IO`.

    #define rb_gzwriter_addstr  rb_io_addstr

comment=(p1) click to toggle source

Specify the comment (`str`) in the gzip header.

    static VALUE
    rb_gzfile_set_comment(VALUE obj, VALUE str)
    {
        struct gzfile *gz = get_gzfile(obj);
        VALUE s;
        char *p;

        if (gz->z.flags & GZFILE_FLAG_HEADER_FINISHED) {
            rb_raise(cGzError, "header is already written");
        }
        s = rb_str_dup(rb_str_to_str(str));
        p = memchr(RSTRING_PTR(s), '\0', RSTRING_LEN(s));
        if (p) {
            rb_str_resize(s, p - RSTRING_PTR(s));
        }
        gz->comment = s;
        return str;
    }

flush(flush=nil) click to toggle source

Flushes all the internal buffers of the `GzipWriter` object. The meaning of `flush` is same as in `Zlib::Deflate#deflate`. `Zlib::SYNC_FLUSH` is used if `flush` is omitted. It is no use giving flush `Zlib::NO_FLUSH`.

    static VALUE
    rb_gzwriter_flush(int argc, VALUE *argv, VALUE obj)
    {
        struct gzfile *gz = get_gzfile(obj);
        VALUE v_flush;
        int flush;

        rb_scan_args(argc, argv, "01", &v_flush);

        flush = FIXNUMARG(v_flush, Z_SYNC_FLUSH);
        if (flush != Z_NO_FLUSH) {  /* prevent Z_BUF_ERROR */
            zstream_run(&gz->z, (Bytef*)"", 0, flush);
        }

        gzfile_write_raw(gz);
        if (rb_respond_to(gz->io, id_flush)) {
            rb_funcall(gz->io, id_flush, 0);
        }
        return obj;
    }

mtime=(p1) click to toggle source

Specify the modification time (`mtime`) in the gzip header. Using an `Integer`.

Setting the mtime in the gzip header does not effect the mtime of the file generated. Different utilities that expand the gzipped files may use the mtime header. For example the gunzip utility can use the ‘-N` flag which will set the resultant file’s mtime to the value in the header. By default many tools will set the mtime of the expanded file to the mtime of the gzipped file, not the mtime in the header.

If you do not set an mtime, the default value will be the time when compression started. Setting a value of 0 indicates no time stamp is available.

    static VALUE
    rb_gzfile_set_mtime(VALUE obj, VALUE mtime)
    {
        struct gzfile *gz = get_gzfile(obj);
        VALUE val;

        if (gz->z.flags & GZFILE_FLAG_HEADER_FINISHED) {
            rb_raise(cGzError, "header is already written");
        }

        val = rb_Integer(mtime);
        gz->mtime = NUM2UINT(val);
        gz->z.flags |= GZFILE_FLAG_MTIME_IS_SET;

        return mtime;
    }

orig_name=(p1) click to toggle source

Specify the original name (`str`) in the gzip header.

    static VALUE
    rb_gzfile_set_orig_name(VALUE obj, VALUE str)
    {
        struct gzfile *gz = get_gzfile(obj);
        VALUE s;
        char *p;

        if (gz->z.flags & GZFILE_FLAG_HEADER_FINISHED) {
            rb_raise(cGzError, "header is already written");
        }
        s = rb_str_dup(rb_str_to_str(str));
        p = memchr(RSTRING_PTR(s), '\0', RSTRING_LEN(s));
        if (p) {
            rb_str_resize(s, p - RSTRING_PTR(s));
        }
        gz->orig_name = s;
        return str;
    }

pos() click to toggle source

Total number of input bytes read so far.

    static VALUE
    rb_gzfile_total_in(VALUE obj)
    {
        return rb_uint2inum(get_gzfile(obj)->z.stream.total_in);
    }

Also aliased as: tell
print(*args) click to toggle source

Same as `IO`.

    #define rb_gzwriter_print  rb_io_print

printf(*args) click to toggle source

Same as `IO`.

    #define rb_gzwriter_printf  rb_io_printf

putc(p1) click to toggle source

Same as `IO`.

    static VALUE
    rb_gzwriter_putc(VALUE obj, VALUE ch)
    {
        struct gzfile *gz = get_gzfile(obj);
        char c = NUM2CHR(ch);

        gzfile_write(gz, (Bytef*)&c, 1);
        return ch;
    }

puts(*args) click to toggle source

Same as `IO`.

    #define rb_gzwriter_puts  rb_io_puts

tell()

Total number of input bytes read so far.

Alias for: pos
write(*args) click to toggle source

Same as `IO`.

    static VALUE
    rb_gzwriter_write(int argc, VALUE *argv, VALUE obj)
    {
        struct gzfile *gz = get_gzfile(obj);
        size_t total = 0;

        while (argc-- > 0) {
            VALUE str = *argv++;
            if (!RB_TYPE_P(str, T_STRING))
                str = rb_obj_as_string(str);
            if (gz->enc2 && gz->enc2 != rb_ascii8bit_encoding()) {
                str = rb_str_conv_enc(str, rb_enc_get(str), gz->enc2);
            }
            gzfile_write(gz, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str));
            total += RSTRING_LEN(str);
            RB_GC_GUARD(str);
        }
        return SIZET2NUM(total);
    }