Module: Omnizip::Formats::Gzip

Defined in:
lib/omnizip/formats/gzip.rb

Overview

GZIP compression format

GZIP is a file compression format that wraps Deflate compression with a 10-byte header and 8-byte footer containing CRC32 and uncompressed size.

Format structure:

  • Header (10 bytes minimum):
    • Magic bytes: 0x1F 0x8B
    • Compression method: 0x08 (Deflate)
    • Flags
    • Modification time (4 bytes)
    • Extra flags
    • OS type
  • Compressed data (Deflate)
  • Footer (8 bytes):
    • CRC32 (4 bytes)
    • Uncompressed size (4 bytes, modulo 2^32)

Constant Summary collapse

GZIP_MAGIC =

GZIP magic bytes

[0x1F, 0x8B].pack("C*")
CM_DEFLATE =

Compression method (Deflate)

8
FTEXT =

Flag bits

0x01
FHCRC =

File is text

0x02
FEXTRA =

Header CRC present

0x04
FNAME =

Extra fields present

0x08
FCOMMENT =

Original filename present

0x10
OS_FAT =

OS types

0
OS_UNIX =

FAT filesystem

3
OS_UNKNOWN =

Unix

255

Class Method Summary collapse

Class Method Details

.compress(input_path, output_path, options = {}) ⇒ Object

Compress a file with GZIP

Parameters:

  • input_path (String)

    Input file path

  • output_path (String)

    Output GZIP file path

  • options (Hash) (defaults to: {})

    Compression options

Options Hash (options):

  • :level (Integer)

    Compression level (0-9)

  • :original_name (String)

    Original filename

  • :mtime (Time)

    Modification time



54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/omnizip/formats/gzip.rb', line 54

def compress(input_path, output_path, options = {})
  input_data = File.binread(input_path)

  File.open(output_path, "wb") do |output|
    original_name = options[:original_name] ||
      File.basename(input_path)
    compress_stream(
      StringIO.new(input_data),
      output,
      options.merge(original_name: original_name),
    )
  end
end

.compress_stream(input_io, output_io, options = {}) ⇒ Object

Compress data stream with GZIP

Parameters:

  • input_io (IO)

    Input stream

  • output_io (IO)

    Output stream

  • options (Hash) (defaults to: {})

    Compression options



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/omnizip/formats/gzip.rb', line 85

def compress_stream(input_io, output_io, options = {})
  input_data = input_io.read
  level = options[:level] || Zlib::DEFAULT_COMPRESSION
  mtime = options[:mtime] || Time.now
  original_name = options[:original_name]

  # Write GZIP header
  write_header(output_io, mtime, original_name)

  # Compress data with Deflate
  deflate = Zlib::Deflate.new(
    level,
    Zlib::MAX_WBITS + 16, # Use GZIP wrapper
  )
  compressed = deflate.deflate(input_data, Zlib::FINISH)
  deflate.close

  # Extract just the compressed data (remove zlib's GZIP wrapper)
  # We'll write our own footer
  output_io.write(compressed[0...-8]) if compressed.bytesize > 8

  # Write GZIP footer
  write_footer(output_io, input_data)
end

.decompress(input_path, output_path) ⇒ Object

Decompress a GZIP file

Parameters:

  • input_path (String)

    Input GZIP file path

  • output_path (String)

    Output file path



72
73
74
75
76
77
78
# File 'lib/omnizip/formats/gzip.rb', line 72

def decompress(input_path, output_path)
  File.open(input_path, "rb") do |input|
    File.open(output_path, "wb") do |output|
      decompress_stream(input, output)
    end
  end
end

.decompress_stream(input_io, output_io) ⇒ Hash

Decompress GZIP stream

Parameters:

  • input_io (IO)

    Input stream

  • output_io (IO)

    Output stream

Returns:

  • (Hash)

    Metadata (original_name, mtime)



115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/omnizip/formats/gzip.rb', line 115

def decompress_stream(input_io, output_io)
  # Read and parse header
   = read_header(input_io)

  # Decompress with Deflate
  inflate = Zlib::Inflate.new(Zlib::MAX_WBITS + 16)
  decompressed = inflate.inflate(input_io.read)
  inflate.close

  # Write decompressed data
  output_io.write(decompressed)

  
end

.register!Object

Register GZIP format when loaded



131
132
133
134
# File 'lib/omnizip/formats/gzip.rb', line 131

def register!
  FormatRegistry.register(".gz", Omnizip::Formats::Gzip)
  FormatRegistry.register(".gzip", Omnizip::Formats::Gzip)
end