class Zip::ZipFile

ZipFile is modeled after java.util.zip.ZipFile from the Java SDK. The most important methods are those inherited from ZipCentralDirectory for accessing information about the entries in the archive and methods such as #get_input_stream and #get_output_stream for reading from and writing entries to the archive. The class includes a few convenience methods such as extract for extracting entries to the filesystem, and remove, replace, rename and mkdir for making simple modifications to the archive.

Modifications to a zip archive are not committed until commit or close is called. The method open accepts a block following the pattern from File.open offering a simple way to automatically close the archive when the block returns.

The following example opens zip archive my.zip (creating it if it doesn’t exist) and adds an entry first.txt and a directory entry a_dir to it.

require 'zip/zip'

Zip::ZipFile.open("my.zip", Zip::ZipFile::CREATE) {
 |zipfile|
  zipfile.get_output_stream("first.txt") { |f| f.puts "Hello from ZipFile" }
  zipfile.mkdir("a_dir")
}

The next example reopens my.zip writes the contents of first.txt to standard out and deletes the entry from the archive.

require 'zip/zip'

Zip::ZipFile.open("my.zip", Zip::ZipFile::CREATE) {
  |zipfile|
  puts zipfile.read("first.txt")
  zipfile.remove("first.txt")
}

ZipFileSystem offers an alternative API that emulates ruby's interface for accessing the filesystem, ie. the File and Dir classes.

Constants

CREATE

Attributes

comment[RW]

Returns the zip files comment, if it has one

name[R]
restore_ownership[RW]

default -> false

restore_permissions[RW]

default -> false

restore_times[RW]

default -> true

Public Class Methods

add_buffer() { |zf| ... } click to toggle source

Same as open. But outputs data to a buffer instead of a file

# File lib/zip/zip_file.rb, line 100
def add_buffer
  zf = ZipFile.new('', true, true)
  yield zf
  zf.write_buffer
end
foreach(aZipFileName, &block) click to toggle source

Iterates over the contents of the ZipFile. This is more efficient than using a ZipInputStream since this methods simply iterates through the entries in the central directory structure in the archive whereas ZipInputStream jumps through the entire archive accessing the local entry headers (which contain the same information as the central directory).

# File lib/zip/zip_file.rb, line 130
def foreach(aZipFileName, &block)
  open(aZipFileName) do |zipFile|
    zipFile.each(&block)
  end
end
new(fileName, create = nil, buffer = false) click to toggle source

Opens a zip archive. Pass true as the second parameter to create a new archive if it doesn’t exist already.

# File lib/zip/zip_file.rb, line 60
def initialize(fileName, create = nil, buffer = false)
  super()
  @name = fileName
  @comment = ""
  case
    when ::File.exists?(fileName) && !buffer
      ::File.open(name, "rb") do |f|
        read_from_stream(f)
      end
    when create
      @entrySet = ZipEntrySet.new
    else
      raise ZipError, "File #{fileName} not found"
  end
  @create = create
  @storedEntries = @entrySet.dup
  @storedComment = @comment
  @restore_ownership = false
  @restore_permissions = false
  @restore_times = true
end
open(fileName, create = nil) { |zf| ... } click to toggle source

Same as new. If a block is passed the ZipFile object is passed to the block and is automatically closed afterwards just as with ruby’s builtin File.open method.

# File lib/zip/zip_file.rb, line 86
def open(fileName, create = nil)
  zf = ZipFile.new(fileName, create)
  if block_given?
    begin
      yield zf
    ensure
      zf.close
    end
  else
    zf
  end
end
open_buffer(io) { |zf| ... } click to toggle source

Like open, but reads zip archive contents from a String or open IO stream, and outputs data to a buffer. (This can be used to extract data from a downloaded zip archive without first saving it to disk.)

# File lib/zip/zip_file.rb, line 110
def open_buffer(io)
  zf = ZipFile.new('',true,true)
  if io.is_a? IO
    zf.read_from_stream(io)
  elsif io.is_a? String
    require 'stringio'
    zf.read_from_stream(StringIO.new(io))
  else
    raise "Zip::ZipFile.open_buffer expects an argument of class String or IO. Found: #{io.class}"
  end
  yield zf
  zf.write_buffer
end

Public Instance Methods

add(entry, srcPath, &continueOnExistsProc) click to toggle source

Convenience method for adding the contents of a file to the archive

# File lib/zip/zip_file.rb, line 173
def add(entry, srcPath, &continueOnExistsProc)
  continueOnExistsProc ||= proc { Zip.options[:continue_on_exists_proc] }
  check_entry_exists(entry, continueOnExistsProc, "add")
  newEntry = entry.kind_of?(ZipEntry) ? entry : ZipEntry.new(@name, entry.to_s)
  newEntry.gather_fileinfo_from_srcpath(srcPath)
  @entrySet << newEntry
end
close() click to toggle source

Closes the zip file committing any changes that has been made.

# File lib/zip/zip_file.rb, line 241
def close
  commit
end
commit() click to toggle source

Commits changes that has been made since the previous commit to the zip archive.

# File lib/zip/zip_file.rb, line 212
def commit
  return if !commit_required?
  on_success_replace(name) {
    |tmpFile|
    ZipOutputStream.open(tmpFile) {
      |zos|

      @entrySet.each {
        |e|
        e.write_to_zip_output_stream(zos)
        e.dirty = false
      }
      zos.comment = comment
    }
    true
  }
  initialize(name)
end
commit_required?() click to toggle source

Returns true if any changes has been made to this archive since the previous commit

# File lib/zip/zip_file.rb, line 247
def commit_required?
  @entrySet.each do |e|
    return true if e.dirty
  end
  @comment != @storedComment || @entrySet != @storedEntries || @create == ZipFile::CREATE
end
extract(entry, destPath, &onExistsProc) click to toggle source

Extracts entry to file destPath.

# File lib/zip/zip_file.rb, line 204
def extract(entry, destPath, &onExistsProc)
  onExistsProc ||= proc { Zip.options[:on_exists_proc] }
  foundEntry = get_entry(entry)
  foundEntry.extract(destPath, &onExistsProc)
end
find_entry(entry_name) click to toggle source

Searches for entry with the specified name. Returns nil if no entry is found. See also #get_entry

# File lib/zip/zip_file.rb, line 256
def find_entry(entry_name)
  @entrySet.find_entry(entry_name)
end
get_entry(entry) click to toggle source

Searches for an entry just as #find_entry, but throws Errno::ENOENT if no entry is found.

# File lib/zip/zip_file.rb, line 267
def get_entry(entry)
  selectedEntry = find_entry(entry)
  unless selectedEntry
    raise Errno::ENOENT, entry
  end
  selectedEntry.restore_ownership = @restore_ownership
  selectedEntry.restore_permissions = @restore_permissions
  selectedEntry.restore_times = @restore_times
  selectedEntry
end
get_input_stream(entry, &aProc) click to toggle source

Returns an input stream to the specified entry. If a block is passed the stream object is passed to the block and the stream is automatically closed afterwards just as with ruby’s builtin File.open method.

# File lib/zip/zip_file.rb, line 143
def get_input_stream(entry, &aProc)
  get_entry(entry).get_input_stream(&aProc)
end
get_output_stream(entry, permissionInt = nil, &aProc) click to toggle source

Returns an output stream to the specified entry. If a block is passed the stream object is passed to the block and the stream is automatically closed afterwards just as with ruby’s builtin File.open method.

# File lib/zip/zip_file.rb, line 150
def get_output_stream(entry, permissionInt = nil, &aProc)
  newEntry = entry.kind_of?(ZipEntry) ? entry : ZipEntry.new(@name, entry.to_s)
  if newEntry.directory?
    raise ArgumentError,
      "cannot open stream to directory entry - '#{newEntry}'"
  end
  newEntry.unix_perms = permissionInt
  zipStreamableEntry = ZipStreamableStream.new(newEntry)
  @entrySet << zipStreamableEntry
  zipStreamableEntry.get_output_stream(&aProc)
end
glob(*args,&block) click to toggle source

Searches for entries given a glob

# File lib/zip/zip_file.rb, line 261
def glob(*args,&block)
  @entrySet.glob(*args,&block)
end
mkdir(entryName, permissionInt = 0755) click to toggle source

Creates a directory

# File lib/zip/zip_file.rb, line 279
def mkdir(entryName, permissionInt = 0755)
  if find_entry(entryName)
    raise Errno::EEXIST, "File exists - #{entryName}"
  end
  entryName = entryName.dup.to_s
  entryName << '/' unless entryName.end_with?('/')
  @entrySet << ZipStreamableDirectory.new(@name, entryName, nil, permissionInt)
end
read(entry) click to toggle source

Returns a string containing the contents of the specified entry

# File lib/zip/zip_file.rb, line 168
def read(entry)
  get_input_stream(entry) { |is| is.read }
end
remove(entry) click to toggle source

Removes the specified entry.

# File lib/zip/zip_file.rb, line 182
def remove(entry)
  @entrySet.delete(get_entry(entry))
end
rename(entry, newName, &continueOnExistsProc) click to toggle source

Renames the specified entry.

# File lib/zip/zip_file.rb, line 187
def rename(entry, newName, &continueOnExistsProc)
  foundEntry = get_entry(entry)
  check_entry_exists(newName, continueOnExistsProc, "rename")
  @entrySet.delete(foundEntry)
  foundEntry.name = newName
  @entrySet << foundEntry
end
replace(entry, srcPath) click to toggle source

Replaces the specified entry with the contents of srcPath (from the file system).

# File lib/zip/zip_file.rb, line 197
def replace(entry, srcPath)
  check_file(srcPath)
  remove(entry)
  add(entry, srcPath)
end
to_s() click to toggle source

Returns the name of the zip archive

# File lib/zip/zip_file.rb, line 163
def to_s
  @name
end
write_buffer() click to toggle source

Write buffer write changes to buffer and return

# File lib/zip/zip_file.rb, line 232
def write_buffer
  buffer = ZipOutputStream.write_buffer do |zos|
    @entrySet.each { |e| e.write_to_zip_output_stream(zos) }
    zos.comment = comment
  end
  return buffer
end