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.



3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
# File 'ext/zlib/zlib.c', line 3529

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)) {
	gz->path = rb_funcall(gz->io, id_path, 0);
	rb_define_singleton_method(obj, "path", rb_gzfile_path, 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)


3510
3511
3512
3513
3514
# File 'ext/zlib/zlib.c', line 3510

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.



3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
# File 'ext/zlib/zlib.c', line 3283

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.



3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
# File 'ext/zlib/zlib.c', line 3570

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.



3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
# File 'ext/zlib/zlib.c', line 3237

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.



3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
# File 'ext/zlib/zlib.c', line 3259

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.



3407
3408
3409
3410
3411
# File 'ext/zlib/zlib.c', line 3407

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.



3617
3618
3619
3620
3621
3622
3623
3624
3625
# File 'ext/zlib/zlib.c', line 3617

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.



3407
3408
3409
3410
3411
# File 'ext/zlib/zlib.c', line 3407

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

#write(*args) ⇒ Object

Same as IO.



3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
# File 'ext/zlib/zlib.c', line 3594

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