Class: Zlib::GzipWriter

Inherits:
GzipFile show all
Defined in:
ext/zlib/zlib.c,
ext/zlib/zlib.c

Overview

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.

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from GzipFile

#close, #closed?, #comment, #crc, #finish, #level, #mtime, #orig_name, #os_code, #sync, #sync=, #to_io, wrap

Constructor Details

#Zlib::GzipWriter.new(io, level = nil, strategy = nil, options = {}) ⇒ Object

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.



3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
# File 'ext/zlib/zlib.c', line 3647

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;
}

Class Method Details

.Zlib::GzipWriter.open(filename, level = nil, strategy = nil) {|gz| ... } ⇒ Object

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.

Yields:

  • (gz)


3628
3629
3630
3631
3632
# File 'ext/zlib/zlib.c', line 3628

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

Instance Method Details

#<<Object

Same as IO.

#comment=(str) ⇒ Object

Specify the comment (str) in the gzip header.



3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
# File 'ext/zlib/zlib.c', line 3391

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) ⇒ Object

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.



3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
# File 'ext/zlib/zlib.c', line 3688

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=(mtime) ⇒ Object

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.



3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
# File 'ext/zlib/zlib.c', line 3345

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=(str) ⇒ Object

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



3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
# File 'ext/zlib/zlib.c', line 3367

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;
}

#posObject

Total number of input bytes read so far.



3515
3516
3517
3518
3519
# File 'ext/zlib/zlib.c', line 3515

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

Same as IO.

#printfObject

Same as IO.

#putc(ch) ⇒ Object

Same as IO.



3735
3736
3737
3738
3739
3740
3741
3742
3743
# File 'ext/zlib/zlib.c', line 3735

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;
}

#putsObject

Same as IO.

#tellObject

Total number of input bytes read so far.



3515
3516
3517
3518
3519
# File 'ext/zlib/zlib.c', line 3515

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

#write(*args) ⇒ Object

Same as IO.



3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
# File 'ext/zlib/zlib.c', line 3712

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);
}