Added a bunch of documentation
This commit is contained in:
parent
93b7add002
commit
3e1aa6d7e5
31
README
31
README
|
@ -4,29 +4,25 @@ rubyzip is a ruby library for reading and writing zip (pkzip format)
|
||||||
files, with the restriction that only uncompressed and deflated zip
|
files, with the restriction that only uncompressed and deflated zip
|
||||||
entries are supported. All this library does is handling of the zip
|
entries are supported. All this library does is handling of the zip
|
||||||
file format. the actual compression/decompression is handled by
|
file format. the actual compression/decompression is handled by
|
||||||
zlib. zlib is accessible from ruby thanks to ruby/zlib (see below)
|
zlib. zlib is accessible from ruby thanks to ruby/zlib.
|
||||||
|
|
||||||
To run the unit tests you need to have rubyunit or test::unit
|
To run the unit tests you need to have test::unit installed.
|
||||||
installed.
|
|
||||||
|
|
||||||
= Install
|
= Install
|
||||||
|
|
||||||
ruby install.rb
|
To install from source run
|
||||||
|
|
||||||
|
ruby install.rb
|
||||||
|
|
||||||
= Prerequisites
|
If you have Rake installed you can build a rubyzip gem with
|
||||||
|
|
||||||
This library requires ruby/zlib version 0.5.0 or newer. ruby/zlib is
|
rake package
|
||||||
included in most recent ruby distributions.
|
|
||||||
|
|
||||||
* zlib http://www.gzip.org/zlib/
|
|
||||||
* ruby-zlib: http://www.blue.sky.or.jp/atelier/ruby/
|
|
||||||
|
|
||||||
|
|
||||||
= Documentation
|
= Documentation
|
||||||
|
|
||||||
There is more than one way to access or create a zip archive with
|
There is more than one way to access or create a zip archive with
|
||||||
rubyzip. The basic API is modelled after the classes in
|
rubyzip. The basic API is modeled after the classes in
|
||||||
java.util.zip.* from the Java SDK. This means there are classes such
|
java.util.zip.* from the Java SDK. This means there are classes such
|
||||||
as Zip::ZipInputStream, Zip::ZipOutputStream and
|
as Zip::ZipInputStream, Zip::ZipOutputStream and
|
||||||
Zip::ZipFile. Zip::ZipInputStream provides a basic interface for
|
Zip::ZipFile. Zip::ZipInputStream provides a basic interface for
|
||||||
|
@ -40,9 +36,9 @@ java.util.zip.ZipFile rubyzip's Zip::ZipFile is mutable, which means
|
||||||
it can be used to change zip files as well.
|
it can be used to change zip files as well.
|
||||||
|
|
||||||
Another way to access a zip archive with rubyzip is to use rubyzip's
|
Another way to access a zip archive with rubyzip is to use rubyzip's
|
||||||
lib/zip/zipfilesystem.rb API. Using this API files can be read from and written
|
Zip::ZipFileSystem API. Using this API files can be read from and
|
||||||
to the archive in much the same manner as ruby's builtin classes
|
written to the archive in much the same manner as ruby's builtin
|
||||||
allows files to be read from and written to the file system.
|
classes allows files to be read from and written to the file system.
|
||||||
|
|
||||||
The samples/ directory is a good place to start to get a feel for
|
The samples/ directory is a good place to start to get a feel for
|
||||||
using the library. For details about the specific behaviour of classes
|
using the library. For details about the specific behaviour of classes
|
||||||
|
@ -59,9 +55,12 @@ http://www.ruby-lang.org/en/LICENSE.txt
|
||||||
|
|
||||||
http://rubyzip.sourceforge.net
|
http://rubyzip.sourceforge.net
|
||||||
|
|
||||||
|
== Download (tarballs and gems)
|
||||||
|
|
||||||
= Author
|
http://sourceforge.net/project/showfiles.php?group_id=43107&package_id=35377
|
||||||
|
|
||||||
Thomas Sondergaard (thomas at thomassondergaard.com)
|
= Authors
|
||||||
|
|
||||||
|
Thomas Sondergaard (thomas at sondergaard.cc)
|
||||||
|
|
||||||
extra-field support contributed by Tatsuki Sugiura (sugi at nemui.org)
|
extra-field support contributed by Tatsuki Sugiura (sugi at nemui.org)
|
||||||
|
|
2
Rakefile
2
Rakefile
|
@ -60,7 +60,7 @@ end
|
||||||
|
|
||||||
Rake::RDocTask.new do |rd|
|
Rake::RDocTask.new do |rd|
|
||||||
rd.main = "README"
|
rd.main = "README"
|
||||||
rd.rdoc_files.add %W{ README NEWS TODO lib/** }
|
rd.rdoc_files.add %W{ lib/zip/*.rb README NEWS TODO }
|
||||||
rd.options << "--title 'rubyzip documentation' --webcvs http://cvs.sourceforge.net/viewcvs.py/rubyzip/rubyzip/"
|
rd.options << "--title 'rubyzip documentation' --webcvs http://cvs.sourceforge.net/viewcvs.py/rubyzip/rubyzip/"
|
||||||
# rd.options << "--all"
|
# rd.options << "--all"
|
||||||
end
|
end
|
||||||
|
|
5
TODO
5
TODO
|
@ -1,9 +1,4 @@
|
||||||
|
|
||||||
* Add an extensively documented sample in samples/ that shows most of
|
|
||||||
what rubyzip does
|
|
||||||
* Add doc target to Rakefile that builds rdoc documentation and which
|
|
||||||
turns the samples in the sample directory into html which is included
|
|
||||||
in the output site
|
|
||||||
* Add web target to Rakefile to update rubyzip.sourceforge.net website
|
* Add web target to Rakefile to update rubyzip.sourceforge.net website
|
||||||
* Add upload target which uploads dist to sourceforge and gem to where-ever
|
* Add upload target which uploads dist to sourceforge and gem to where-ever
|
||||||
* Release 0.5.7
|
* Release 0.5.7
|
||||||
|
|
|
@ -24,7 +24,7 @@ unless Object.method_defined?(:object_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
unless File.respond_to?(:read)
|
unless File.respond_to?(:read)
|
||||||
class File
|
class File # :nodoc:all
|
||||||
# singleton method read does not exist in 1.6.x
|
# singleton method read does not exist in 1.6.x
|
||||||
def self.read(fileName)
|
def self.read(fileName)
|
||||||
open(fileName) { |f| f.read }
|
open(fileName) { |f| f.read }
|
||||||
|
|
121
lib/zip/zip.rb
121
lib/zip/zip.rb
|
@ -735,7 +735,7 @@ module Zip
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
class ZipCentralDirectory #:nodoc:all
|
class ZipCentralDirectory
|
||||||
include Enumerable
|
include Enumerable
|
||||||
|
|
||||||
END_OF_CENTRAL_DIRECTORY_SIGNATURE = 0x06054b50
|
END_OF_CENTRAL_DIRECTORY_SIGNATURE = 0x06054b50
|
||||||
|
@ -743,24 +743,25 @@ module Zip
|
||||||
STATIC_EOCD_SIZE = 22
|
STATIC_EOCD_SIZE = 22
|
||||||
|
|
||||||
attr_reader :comment
|
attr_reader :comment
|
||||||
|
|
||||||
|
# Returns an Enumerable containing the entries.
|
||||||
def entries
|
def entries
|
||||||
@entrySet.entries
|
@entrySet.entries
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(entries = ZipEntrySet.new, comment = "")
|
def initialize(entries = ZipEntrySet.new, comment = "") #:nodoc:
|
||||||
super()
|
super()
|
||||||
@entrySet = entries.kind_of?(ZipEntrySet) ? entries : ZipEntrySet.new(entries)
|
@entrySet = entries.kind_of?(ZipEntrySet) ? entries : ZipEntrySet.new(entries)
|
||||||
@comment = comment
|
@comment = comment
|
||||||
end
|
end
|
||||||
|
|
||||||
def write_to_stream(io)
|
def write_to_stream(io) #:nodoc:
|
||||||
offset = io.tell
|
offset = io.tell
|
||||||
@entrySet.each { |entry| entry.write_c_dir_entry(io) }
|
@entrySet.each { |entry| entry.write_c_dir_entry(io) }
|
||||||
write_e_o_c_d(io, offset)
|
write_e_o_c_d(io, offset)
|
||||||
end
|
end
|
||||||
|
|
||||||
def write_e_o_c_d(io, offset)
|
def write_e_o_c_d(io, offset) #:nodoc:
|
||||||
io <<
|
io <<
|
||||||
[END_OF_CENTRAL_DIRECTORY_SIGNATURE,
|
[END_OF_CENTRAL_DIRECTORY_SIGNATURE,
|
||||||
0 , # @numberOfThisDisk
|
0 , # @numberOfThisDisk
|
||||||
|
@ -774,13 +775,13 @@ module Zip
|
||||||
end
|
end
|
||||||
private :write_e_o_c_d
|
private :write_e_o_c_d
|
||||||
|
|
||||||
def cdir_size
|
def cdir_size #:nodoc:
|
||||||
# does not include eocd
|
# does not include eocd
|
||||||
@entrySet.inject(0) { |value, entry| entry.cdir_header_size + value }
|
@entrySet.inject(0) { |value, entry| entry.cdir_header_size + value }
|
||||||
end
|
end
|
||||||
private :cdir_size
|
private :cdir_size
|
||||||
|
|
||||||
def read_e_o_c_d(io)
|
def read_e_o_c_d(io) #:nodoc:
|
||||||
buf = get_e_o_c_d(io)
|
buf = get_e_o_c_d(io)
|
||||||
@numberOfThisDisk = ZipEntry::read_zip_short(buf)
|
@numberOfThisDisk = ZipEntry::read_zip_short(buf)
|
||||||
@numberOfDiskWithStartOfCDir = ZipEntry::read_zip_short(buf)
|
@numberOfDiskWithStartOfCDir = ZipEntry::read_zip_short(buf)
|
||||||
|
@ -793,7 +794,7 @@ module Zip
|
||||||
raise ZipError, "Zip consistency problem while reading eocd structure" unless buf.size == 0
|
raise ZipError, "Zip consistency problem while reading eocd structure" unless buf.size == 0
|
||||||
end
|
end
|
||||||
|
|
||||||
def read_central_directory_entries(io)
|
def read_central_directory_entries(io) #:nodoc:
|
||||||
begin
|
begin
|
||||||
io.seek(@cdirOffset, IO::SEEK_SET)
|
io.seek(@cdirOffset, IO::SEEK_SET)
|
||||||
rescue Errno::EINVAL
|
rescue Errno::EINVAL
|
||||||
|
@ -805,12 +806,12 @@ module Zip
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def read_from_stream(io)
|
def read_from_stream(io) #:nodoc:
|
||||||
read_e_o_c_d(io)
|
read_e_o_c_d(io)
|
||||||
read_central_directory_entries(io)
|
read_central_directory_entries(io)
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_e_o_c_d(io)
|
def get_e_o_c_d(io) #:nodoc:
|
||||||
begin
|
begin
|
||||||
io.seek(-MAX_END_OF_CENTRAL_DIRECTORY_STRUCTURE_SIZE, IO::SEEK_END)
|
io.seek(-MAX_END_OF_CENTRAL_DIRECTORY_STRUCTURE_SIZE, IO::SEEK_END)
|
||||||
rescue Errno::EINVAL
|
rescue Errno::EINVAL
|
||||||
|
@ -827,16 +828,19 @@ module Zip
|
||||||
end
|
end
|
||||||
return buf
|
return buf
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# For iterating over the entries.
|
||||||
def each(&proc)
|
def each(&proc)
|
||||||
@entrySet.each(&proc)
|
@entrySet.each(&proc)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns the number of entries in the central directory (and
|
||||||
|
# consequently in the zip archive).
|
||||||
def size
|
def size
|
||||||
@entrySet.size
|
@entrySet.size
|
||||||
end
|
end
|
||||||
|
|
||||||
def ZipCentralDirectory.read_from_stream(io)
|
def ZipCentralDirectory.read_from_stream(io) #:nodoc:
|
||||||
cdir = new
|
cdir = new
|
||||||
cdir.read_from_stream(io)
|
cdir.read_from_stream(io)
|
||||||
return cdir
|
return cdir
|
||||||
|
@ -844,7 +848,7 @@ module Zip
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def == (other)
|
def == (other) #:nodoc:
|
||||||
return false unless other.kind_of?(ZipCentralDirectory)
|
return false unless other.kind_of?(ZipCentralDirectory)
|
||||||
@entrySet.entries.sort == other.entries.sort && comment == other.comment
|
@entrySet.entries.sort == other.entries.sort && comment == other.comment
|
||||||
end
|
end
|
||||||
|
@ -858,19 +862,64 @@ module Zip
|
||||||
class ZipCompressionMethodError < ZipError; end
|
class ZipCompressionMethodError < ZipError; end
|
||||||
class ZipEntryNameError < ZipError; end
|
class ZipEntryNameError < ZipError; end
|
||||||
|
|
||||||
|
# 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 <code>my.zip</code>
|
||||||
|
# (creating it if it doesn't exist) and adds an entry
|
||||||
|
# <code>first.txt</code> and a directory entry <code>a_dir</code>
|
||||||
|
# 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 <code>my.zip</code> writes the contents of
|
||||||
|
# <code>first.txt</code> 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.
|
||||||
|
|
||||||
class ZipFile < ZipCentralDirectory
|
class ZipFile < ZipCentralDirectory
|
||||||
|
|
||||||
CREATE = 1
|
CREATE = 1
|
||||||
|
|
||||||
attr_reader :name
|
attr_reader :name
|
||||||
|
|
||||||
|
# Opens a zip archive. Pass true as the second parameter to create
|
||||||
|
# a new archive if it doesn't exist already.
|
||||||
def initialize(fileName, create = nil)
|
def initialize(fileName, create = nil)
|
||||||
super()
|
super()
|
||||||
@name = fileName
|
@name = fileName
|
||||||
@comment = ""
|
@comment = ""
|
||||||
if (File.exists?(fileName))
|
if (File.exists?(fileName))
|
||||||
File.open(name, "rb") { |f| read_from_stream(f) }
|
File.open(name, "rb") { |f| read_from_stream(f) }
|
||||||
elsif (create == ZipFile::CREATE)
|
elsif (create)
|
||||||
@entrySet = ZipEntrySet.new
|
@entrySet = ZipEntrySet.new
|
||||||
else
|
else
|
||||||
raise ZipError, "File #{fileName} not found"
|
raise ZipError, "File #{fileName} not found"
|
||||||
|
@ -878,7 +927,10 @@ module Zip
|
||||||
@create = create
|
@create = create
|
||||||
@storedEntries = @entrySet.dup
|
@storedEntries = @entrySet.dup
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# 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.
|
||||||
def ZipFile.open(fileName, create = nil)
|
def ZipFile.open(fileName, create = nil)
|
||||||
zf = ZipFile.new(fileName, create)
|
zf = ZipFile.new(fileName, create)
|
||||||
if block_given?
|
if block_given?
|
||||||
|
@ -892,8 +944,15 @@ module Zip
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns the zip files comment, if it has one
|
||||||
attr_accessor :comment
|
attr_accessor :comment
|
||||||
|
|
||||||
|
# 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).
|
||||||
def ZipFile.foreach(aZipFileName, &block)
|
def ZipFile.foreach(aZipFileName, &block)
|
||||||
ZipFile.open(aZipFileName) {
|
ZipFile.open(aZipFileName) {
|
||||||
|zipFile|
|
|zipFile|
|
||||||
|
@ -901,10 +960,16 @@ module Zip
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# 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.
|
||||||
def get_input_stream(entry, &aProc)
|
def get_input_stream(entry, &aProc)
|
||||||
get_entry(entry).get_input_stream(&aProc)
|
get_entry(entry).get_input_stream(&aProc)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# 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.
|
||||||
def get_output_stream(entry, &aProc)
|
def get_output_stream(entry, &aProc)
|
||||||
newEntry = entry.kind_of?(ZipEntry) ? entry : ZipEntry.new(@name, entry.to_s)
|
newEntry = entry.kind_of?(ZipEntry) ? entry : ZipEntry.new(@name, entry.to_s)
|
||||||
if newEntry.directory?
|
if newEntry.directory?
|
||||||
|
@ -916,14 +981,17 @@ module Zip
|
||||||
zipStreamableEntry.get_output_stream(&aProc)
|
zipStreamableEntry.get_output_stream(&aProc)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns the name of the zip archive
|
||||||
def to_s
|
def to_s
|
||||||
@name
|
@name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns a string containing the contents of the specified entry
|
||||||
def read(entry)
|
def read(entry)
|
||||||
get_input_stream(entry) { |is| is.read }
|
get_input_stream(entry) { |is| is.read }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Convenience method for adding the contents of a file to the archive
|
||||||
def add(entry, srcPath, &continueOnExistsProc)
|
def add(entry, srcPath, &continueOnExistsProc)
|
||||||
continueOnExistsProc ||= proc { false }
|
continueOnExistsProc ||= proc { false }
|
||||||
check_entry_exists(entry, continueOnExistsProc, "add")
|
check_entry_exists(entry, continueOnExistsProc, "add")
|
||||||
|
@ -935,21 +1003,26 @@ module Zip
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Removes the specified entry.
|
||||||
def remove(entry)
|
def remove(entry)
|
||||||
@entrySet.delete(get_entry(entry))
|
@entrySet.delete(get_entry(entry))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Renames the specified entry.
|
||||||
def rename(entry, newName, &continueOnExistsProc)
|
def rename(entry, newName, &continueOnExistsProc)
|
||||||
foundEntry = get_entry(entry)
|
foundEntry = get_entry(entry)
|
||||||
check_entry_exists(newName, continueOnExistsProc, "rename")
|
check_entry_exists(newName, continueOnExistsProc, "rename")
|
||||||
foundEntry.name=newName
|
foundEntry.name=newName
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Replaces the specified entry with the contents of srcPath (from
|
||||||
|
# the file system).
|
||||||
def replace(entry, srcPath)
|
def replace(entry, srcPath)
|
||||||
check_file(srcPath)
|
check_file(srcPath)
|
||||||
add(remove(entry), srcPath)
|
add(remove(entry), srcPath)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Extracts entry to file destPath.
|
||||||
def extract(entry, destPath, &onExistsProc)
|
def extract(entry, destPath, &onExistsProc)
|
||||||
onExistsProc ||= proc { false }
|
onExistsProc ||= proc { false }
|
||||||
foundEntry = get_entry(entry)
|
foundEntry = get_entry(entry)
|
||||||
|
@ -959,7 +1032,9 @@ module Zip
|
||||||
write_file(foundEntry, destPath, &onExistsProc)
|
write_file(foundEntry, destPath, &onExistsProc)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Commits changes that has been made since the previous commit to
|
||||||
|
# the zip archive.
|
||||||
def commit
|
def commit
|
||||||
return if ! commit_required?
|
return if ! commit_required?
|
||||||
on_success_replace(name) {
|
on_success_replace(name) {
|
||||||
|
@ -974,22 +1049,29 @@ module Zip
|
||||||
}
|
}
|
||||||
initialize(name)
|
initialize(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Closes the zip file committing any changes that has been made.
|
||||||
def close
|
def close
|
||||||
commit
|
commit
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns true if any changes has been made to this archive since
|
||||||
|
# the previous commit
|
||||||
def commit_required?
|
def commit_required?
|
||||||
return @entrySet != @storedEntries || @create == ZipFile::CREATE
|
return @entrySet != @storedEntries || @create == ZipFile::CREATE
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Searches for entry with the specified name. Returns nil if
|
||||||
|
# no entry is found. See also get_entry
|
||||||
def find_entry(entry)
|
def find_entry(entry)
|
||||||
@entrySet.detect {
|
@entrySet.detect {
|
||||||
|e|
|
|e|
|
||||||
e.name.sub(/\/$/, "") == entry.to_s.sub(/\/$/, "")
|
e.name.sub(/\/$/, "") == entry.to_s.sub(/\/$/, "")
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Searches for an entry just as find_entry, but throws Errno::ENOENT
|
||||||
|
# if no entry is found.
|
||||||
def get_entry(entry)
|
def get_entry(entry)
|
||||||
selectedEntry = find_entry(entry)
|
selectedEntry = find_entry(entry)
|
||||||
unless selectedEntry
|
unless selectedEntry
|
||||||
|
@ -998,6 +1080,7 @@ module Zip
|
||||||
return selectedEntry
|
return selectedEntry
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Creates a directory
|
||||||
def mkdir(entryName, permissionInt = 0) #permissionInt ignored
|
def mkdir(entryName, permissionInt = 0) #permissionInt ignored
|
||||||
if find_entry(entryName)
|
if find_entry(entryName)
|
||||||
raise Errno::EEXIST, "File exists - #{entryName}"
|
raise Errno::EEXIST, "File exists - #{entryName}"
|
||||||
|
|
|
@ -1,9 +1,42 @@
|
||||||
require 'zip/zip'
|
require 'zip/zip'
|
||||||
|
|
||||||
module Zip
|
module Zip
|
||||||
|
|
||||||
|
# The ZipFileSystem API provides an API for accessing entries in
|
||||||
|
# a zip archive that is similar to ruby's builtin File and Dir
|
||||||
|
# classes.
|
||||||
|
#
|
||||||
|
# Requiring 'zip/zipfilesystem' includes this module in ZipFile
|
||||||
|
# making the methods in this module available on ZipFile objects.
|
||||||
|
#
|
||||||
|
# Using this API the following example creates a new zip file
|
||||||
|
# <code>my.zip</code> containing a normal entry with the name
|
||||||
|
# <code>first.txt</code>, a directory entry named <code>mydir</code>
|
||||||
|
# and finally another normal entry named <code>second.txt</code>
|
||||||
|
#
|
||||||
|
# require 'zip/zipfilesystem'
|
||||||
|
#
|
||||||
|
# Zip::ZipFile.open("my.zip", Zip::ZipFile::CREATE) {
|
||||||
|
# |zipfile|
|
||||||
|
# zipfile.file.open("first.txt", "w") { |f| f.puts "Hello world" }
|
||||||
|
# zipfile.dir.mkdir("mydir")
|
||||||
|
# zipfile.file.open("mydir/second.txt", "w") { |f| f.puts "Hello again" }
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# Reading is as easy as writing, as the following example shows. The
|
||||||
|
# example writes the contents of <code>first.txt</code> from zip archive
|
||||||
|
# <code>my.zip</code> to standard out.
|
||||||
|
#
|
||||||
|
# require 'zip/zipfilesystem'
|
||||||
|
#
|
||||||
|
# Zip::ZipFile.open("my.zip") {
|
||||||
|
# |zipfile|
|
||||||
|
# puts zipfile.file.read("first.txt")
|
||||||
|
# }
|
||||||
|
|
||||||
module ZipFileSystem
|
module ZipFileSystem
|
||||||
|
|
||||||
def initialize
|
def initialize # :nodoc:
|
||||||
mappedZip = ZipFileNameMapper.new(self)
|
mappedZip = ZipFileNameMapper.new(self)
|
||||||
@zipFsDir = ZipFsDir.new(mappedZip)
|
@zipFsDir = ZipFsDir.new(mappedZip)
|
||||||
@zipFsFile = ZipFsFile.new(mappedZip)
|
@zipFsFile = ZipFsFile.new(mappedZip)
|
||||||
|
@ -11,14 +44,26 @@ module Zip
|
||||||
@zipFsFile.dir = @zipFsDir
|
@zipFsFile.dir = @zipFsDir
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns a ZipFsDir which is much like ruby's builtin Dir (class)
|
||||||
|
# object, except it works on the ZipFile on which this method is
|
||||||
|
# invoked
|
||||||
def dir
|
def dir
|
||||||
@zipFsDir
|
@zipFsDir
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns a ZipFsFile which is much like ruby's builtin File (class)
|
||||||
|
# object, except it works on the ZipFile on which this method is
|
||||||
|
# invoked
|
||||||
def file
|
def file
|
||||||
@zipFsFile
|
@zipFsFile
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Instances of this class are normally accessed via the accessor
|
||||||
|
# ZipFile::file. An instance of ZipFsFile behaves like ruby's
|
||||||
|
# builtin File (class) object, except it works on ZipFile entries.
|
||||||
|
#
|
||||||
|
# The individual methods are not documented due to their
|
||||||
|
# similarity with the methods in File
|
||||||
class ZipFsFile
|
class ZipFsFile
|
||||||
|
|
||||||
attr_writer :dir
|
attr_writer :dir
|
||||||
|
@ -198,7 +243,7 @@ module Zip
|
||||||
@mappedZip.get_entry(fileName).size
|
@mappedZip.get_entry(fileName).size
|
||||||
end
|
end
|
||||||
|
|
||||||
# nil for not found and nil for directories
|
# Returns nil for not found and nil for directories
|
||||||
def size?(fileName)
|
def size?(fileName)
|
||||||
entry = @mappedZip.find_entry(fileName)
|
entry = @mappedZip.find_entry(fileName)
|
||||||
return (entry == nil || entry.directory?) ? nil : entry.size
|
return (entry == nil || entry.directory?) ? nil : entry.size
|
||||||
|
@ -367,6 +412,12 @@ module Zip
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Instances of this class are normally accessed via the accessor
|
||||||
|
# ZipFile::dir. An instance of ZipFsDir behaves like ruby's
|
||||||
|
# builtin Dir (class) object, except it works on ZipFile entries.
|
||||||
|
#
|
||||||
|
# The individual methods are not documented due to their
|
||||||
|
# similarity with the methods in Dir
|
||||||
class ZipFsDir
|
class ZipFsDir
|
||||||
|
|
||||||
def initialize(mappedZip)
|
def initialize(mappedZip)
|
||||||
|
@ -441,7 +492,7 @@ module Zip
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class ZipFsDirIterator
|
class ZipFsDirIterator # :nodoc:all
|
||||||
include Enumerable
|
include Enumerable
|
||||||
|
|
||||||
def initialize(arrayOfFileNames)
|
def initialize(arrayOfFileNames)
|
||||||
|
@ -481,7 +532,7 @@ module Zip
|
||||||
|
|
||||||
# All access to ZipFile from ZipFsFile and ZipFsDir goes through a
|
# All access to ZipFile from ZipFsFile and ZipFsDir goes through a
|
||||||
# ZipFileNameMapper, which has one responsibility: ensure
|
# ZipFileNameMapper, which has one responsibility: ensure
|
||||||
class ZipFileNameMapper
|
class ZipFileNameMapper # :nodoc:all
|
||||||
include Enumerable
|
include Enumerable
|
||||||
|
|
||||||
def initialize(zipFile)
|
def initialize(zipFile)
|
||||||
|
|
Loading…
Reference in New Issue