Zip write support is now fully functional in the form of ZipOutputStream.
This commit is contained in:
parent
559c8032ea
commit
c6f5747df7
4
NEWS
4
NEWS
|
@ -1,3 +1,7 @@
|
|||
= Version 0.3.0 =
|
||||
|
||||
Rudimentary support for writing zip archives.
|
||||
|
||||
= Version 0.2.2 =
|
||||
|
||||
Fixed and extended unit test suite. Updated to work with ruby/zlib
|
||||
|
|
|
@ -18,6 +18,9 @@ ruby-zlib: http://www.blue.sky.or.jp/atelier/#ruby-zlib
|
|||
|
||||
This library requires ruby/zlib version 0.5.0 or newer.
|
||||
|
||||
As of this writing ruby/zlib 0.5.0 is only available as
|
||||
ruby-zlib-0.5.0-pre3 at http://www.blue.sky.or.jp/atelier/ruby/
|
||||
|
||||
|
||||
= LICENSE =
|
||||
|
||||
|
|
25
zip.rb
25
zip.rb
|
@ -453,7 +453,7 @@ module Zip
|
|||
@fileName = fileName
|
||||
@outputStream = File.new(@fileName, "wb")
|
||||
@entries = []
|
||||
@compressor = NullCompressor
|
||||
@compressor = NullCompressor.instance
|
||||
end
|
||||
|
||||
def ZipOutputStream.open(fileName)
|
||||
|
@ -483,10 +483,12 @@ module Zip
|
|||
def finalizeCurrentEntry
|
||||
return unless @currentEntry
|
||||
finish
|
||||
@currentEntry.compressedSize = @outputStream.tell - @currentEntry.localHeaderOffset - @currentEntry.localHeaderSize
|
||||
@currentEntry.compressedSize = @outputStream.tell - @currentEntry.localHeaderOffset -
|
||||
@currentEntry.localHeaderSize
|
||||
@currentEntry.size = @compressor.size
|
||||
@currentEntry.crc = @compressor.crc
|
||||
@currentEntry = nil
|
||||
@compressor = NullCompressor
|
||||
@compressor = NullCompressor.instance
|
||||
end
|
||||
|
||||
def initNextEntry(entry, level = Zlib::DEFAULT_COMPRESSION)
|
||||
|
@ -520,13 +522,15 @@ module Zip
|
|||
end
|
||||
|
||||
protected
|
||||
def << (data)
|
||||
@compressor << data
|
||||
end
|
||||
|
||||
def finish
|
||||
@compressor.finish
|
||||
end
|
||||
|
||||
public
|
||||
def << (data)
|
||||
@compressor << data
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
@ -538,22 +542,25 @@ module Zip
|
|||
class PassThruCompressor < Compressor
|
||||
def initialize(outputStream)
|
||||
@outputStream = outputStream
|
||||
@crc = Zlib::crc32
|
||||
@size = 0
|
||||
end
|
||||
|
||||
def << (data)
|
||||
val = data.to_s
|
||||
@crc = Zlib::crc32(val, @crc)
|
||||
@size += val.size
|
||||
@outputStream << val
|
||||
end
|
||||
|
||||
attr_reader :size
|
||||
attr_reader :size, :crc
|
||||
end
|
||||
|
||||
class NullCompressor < Compressor
|
||||
include Singleton
|
||||
|
||||
def << (data)
|
||||
raise IOError, "closed stream"
|
||||
end
|
||||
|
||||
attr_reader :size, :compressedSize
|
||||
|
@ -564,10 +571,12 @@ module Zip
|
|||
@outputStream = outputStream
|
||||
@zlibDeflater = Zlib::Deflate.new(level, -Zlib::Deflate::MAX_WBITS)
|
||||
@size = 0
|
||||
@crc = Zlib::crc32
|
||||
end
|
||||
|
||||
def << (data)
|
||||
val = data.to_s
|
||||
@crc = Zlib::crc32(val, @crc)
|
||||
@size += val.size
|
||||
@outputStream << @zlibDeflater.deflate(data)
|
||||
end
|
||||
|
@ -578,7 +587,7 @@ module Zip
|
|||
end
|
||||
end
|
||||
|
||||
attr_reader :size
|
||||
attr_reader :size, :crc
|
||||
end
|
||||
|
||||
class ZipCentralDirectory
|
||||
|
|
54
ziptest.rb
54
ziptest.rb
|
@ -551,7 +551,23 @@ class AbstractOutputStreamTest < RUNIT::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
module CrcTest
|
||||
def runCrcTest(compressorClass)
|
||||
str = "Here's a nice little text to compute the crc for! Ho hum, it is nice nice nice nice indeed."
|
||||
fakeOut = AbstractOutputStreamTest::TestOutputStream.new
|
||||
|
||||
deflater = compressorClass.new(fakeOut)
|
||||
deflater << str
|
||||
assert_equals(0x919920fc, deflater.crc)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
class PassThruCompressorTest < RUNIT::TestCase
|
||||
include CrcTest
|
||||
|
||||
def test_size
|
||||
File.open("dummy.txt", "wb") {
|
||||
|file|
|
||||
|
@ -573,9 +589,15 @@ class PassThruCompressorTest < RUNIT::TestCase
|
|||
assert_equals(compressor.size, t1.size + t2.size + t3.size)
|
||||
}
|
||||
end
|
||||
|
||||
def test_crc
|
||||
runCrcTest(PassThruCompressor)
|
||||
end
|
||||
end
|
||||
|
||||
class DeflaterTest < RUNIT::TestCase
|
||||
include CrcTest
|
||||
|
||||
def test_outputOperator
|
||||
txt = loadFile("ziptest.rb")
|
||||
deflate(txt, "deflatertest.bin")
|
||||
|
@ -608,8 +630,11 @@ class DeflaterTest < RUNIT::TestCase
|
|||
txt = inflater.read
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def test_crc
|
||||
runCrcTest(Deflater)
|
||||
end
|
||||
end
|
||||
|
||||
class ZipOutputStreamTest < RUNIT::TestCase
|
||||
include AssertEntry
|
||||
|
@ -634,18 +659,33 @@ class ZipOutputStreamTest < RUNIT::TestCase
|
|||
assertTestZipContents(TEST_ZIP)
|
||||
end
|
||||
|
||||
def test_putOnClosedStream
|
||||
fail "implement and expect ZipError"
|
||||
end
|
||||
|
||||
def test_writingToClosedStream
|
||||
fail "implement this test and make sure behaviour is similar to closed File object"
|
||||
assertIOErrorInClosedStream { |zos| zos << "hello world" }
|
||||
assertIOErrorInClosedStream { |zos| zos.puts "hello world" }
|
||||
assertIOErrorInClosedStream { |zos| zos.write "hello world" }
|
||||
end
|
||||
|
||||
def test_cannotOpenFile
|
||||
fail "implement and expect zip.closed? and exception from constructor"
|
||||
name = "emptytestdir"
|
||||
ensureDir(name)
|
||||
assert_exception(Errno::EISDIR, "Is a directorYY") {
|
||||
zos = ZipOutputStream.open(name)
|
||||
}
|
||||
end
|
||||
|
||||
def ensureDir(name)
|
||||
return if File.stat(name).directory?
|
||||
File.delete(name)
|
||||
Dir.mkdir(name)
|
||||
end
|
||||
|
||||
def assertIOErrorInClosedStream
|
||||
assert_exception(IOError) {
|
||||
zos = ZipOutputStream.new("test_putOnClosedStream.zip")
|
||||
zos.close
|
||||
yield zos
|
||||
}
|
||||
end
|
||||
|
||||
def writeTestZip(zos)
|
||||
TEST_ZIP.entryNames.each {
|
||||
|
|
Loading…
Reference in New Issue