Class: Zip::OutputStream

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
IOExtras::AbstractOutputStream
Defined in:
lib/zip/output_stream.rb

Overview

ZipOutputStream is the basic class for writing zip files. It is possible to create a ZipOutputStream object directly, passing the zip file name to the constructor, but more often than not the ZipOutputStream will be obtained from a ZipFile (perhaps using the ZipFileSystem interface) object for a particular entry in the zip archive.

A ZipOutputStream inherits IOExtras::AbstractOutputStream in order to provide an IO-like interface for writing to a single zip entry. Beyond methods for mimicking an IO-object it contains the method put_next_entry that closes the current entry and creates a new.

Please refer to ZipInputStream for example code.

java.util.zip.ZipOutputStream is the original inspiration for this class.

Class Method Summary collapse

Instance Method Summary collapse

Methods included from IOExtras::AbstractOutputStream

#print, #printf, #putc, #puts, #write

Methods included from IOExtras::FakeIO

#kind_of?

Constructor Details

#initialize(file_name, stream: false, encrypter: nil) ⇒ OutputStream

Opens the indicated zip file. If a file with that name already exists it will be overwritten.


32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/zip/output_stream.rb', line 32

def initialize(file_name, stream: false, encrypter: nil)
  super()
  @file_name = file_name
  @output_stream = if stream
                     iostream = Zip::RUNNING_ON_WINDOWS ? @file_name : @file_name.dup
                     iostream.reopen(@file_name)
                     iostream.rewind
                     iostream
                   else
                     ::File.new(@file_name, 'wb')
                   end
  @cdir = ::Zip::CentralDirectory.new
  @compressor = ::Zip::NullCompressor.instance
  @encrypter = encrypter || ::Zip::NullEncrypter.new
  @closed = false
  @current_entry = nil
end

Class Method Details

.open(file_name, encrypter: nil) ⇒ Object


54
55
56
57
58
59
60
61
# File 'lib/zip/output_stream.rb', line 54

def open(file_name, encrypter: nil)
  return new(file_name) unless block_given?

  zos = new(file_name, stream: false, encrypter: encrypter)
  yield zos
ensure
  zos.close if zos
end

.write_buffer(io = ::StringIO.new, encrypter: nil) {|zos| ... } ⇒ Object

Same as #open but writes to a filestream instead

Yields:

  • (zos)

64
65
66
67
68
69
# File 'lib/zip/output_stream.rb', line 64

def write_buffer(io = ::StringIO.new, encrypter: nil)
  io.binmode if io.respond_to?(:binmode)
  zos = new(io, stream: true, encrypter: encrypter)
  yield zos
  zos.close_buffer
end

Instance Method Details

#<<(data) ⇒ Object

Modeled after IO.<<


196
197
198
199
# File 'lib/zip/output_stream.rb', line 196

def <<(data)
  @compressor << data
  self
end

#closeObject

Closes the stream and writes the central directory to the zip file


73
74
75
76
77
78
79
80
81
# File 'lib/zip/output_stream.rb', line 73

def close
  return if @closed

  finalize_current_entry
  update_local_headers
  @cdir.write_to_stream(@output_stream)
  @output_stream.close
  @closed = true
end

#close_bufferObject

Closes the stream and writes the central directory to the zip file


84
85
86
87
88
89
90
91
92
93
# File 'lib/zip/output_stream.rb', line 84

def close_buffer
  return @output_stream if @closed

  finalize_current_entry
  update_local_headers
  @cdir.write_to_stream(@output_stream)
  @closed = true
  @output_stream.flush
  @output_stream
end

#copy_raw_entry(entry) ⇒ Object

Raises:


117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/zip/output_stream.rb', line 117

def copy_raw_entry(entry)
  entry = entry.dup
  raise Error, 'zip stream is closed' if @closed
  raise Error, 'entry is not a ZipEntry' unless entry.kind_of?(Entry)

  finalize_current_entry
  @cdir << entry
  src_pos = entry.local_header_offset
  entry.write_local_entry(@output_stream)
  @compressor = NullCompressor.instance
  entry.get_raw_input_stream do |is|
    is.seek(src_pos, IO::SEEK_SET)
    ::Zip::Entry.read_local_entry(is)
    IOExtras.copy_stream_n(@output_stream, is, entry.compressed_size)
  end
  @compressor = NullCompressor.instance
  @current_entry = nil
end

#put_next_entry(entry_name, comment = '', extra = ExtraField.new, compression_method = Entry::DEFLATED, level = Zip.default_compression) ⇒ Object

Closes the current entry and opens a new for writing. entry can be a ZipEntry object or a string.

Raises:


97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/zip/output_stream.rb', line 97

def put_next_entry(
  entry_name, comment = '', extra = ExtraField.new,
  compression_method = Entry::DEFLATED, level = Zip.default_compression
)
  raise Error, 'zip stream is closed' if @closed

  new_entry =
    if entry_name.kind_of?(Entry) || entry_name.kind_of?(StreamableStream)
      entry_name
    else
      Entry.new(
        @file_name, entry_name.to_s, comment: comment, extra: extra,
        compression_method: compression_method, compression_level: level
      )
    end

  init_next_entry(new_entry)
  @current_entry = new_entry
end