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 =
|
= Version 0.2.2 =
|
||||||
|
|
||||||
Fixed and extended unit test suite. Updated to work with ruby/zlib
|
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.
|
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 =
|
= LICENSE =
|
||||||
|
|
||||||
|
|
25
zip.rb
25
zip.rb
|
@ -453,7 +453,7 @@ module Zip
|
||||||
@fileName = fileName
|
@fileName = fileName
|
||||||
@outputStream = File.new(@fileName, "wb")
|
@outputStream = File.new(@fileName, "wb")
|
||||||
@entries = []
|
@entries = []
|
||||||
@compressor = NullCompressor
|
@compressor = NullCompressor.instance
|
||||||
end
|
end
|
||||||
|
|
||||||
def ZipOutputStream.open(fileName)
|
def ZipOutputStream.open(fileName)
|
||||||
|
@ -483,10 +483,12 @@ module Zip
|
||||||
def finalizeCurrentEntry
|
def finalizeCurrentEntry
|
||||||
return unless @currentEntry
|
return unless @currentEntry
|
||||||
finish
|
finish
|
||||||
@currentEntry.compressedSize = @outputStream.tell - @currentEntry.localHeaderOffset - @currentEntry.localHeaderSize
|
@currentEntry.compressedSize = @outputStream.tell - @currentEntry.localHeaderOffset -
|
||||||
|
@currentEntry.localHeaderSize
|
||||||
@currentEntry.size = @compressor.size
|
@currentEntry.size = @compressor.size
|
||||||
|
@currentEntry.crc = @compressor.crc
|
||||||
@currentEntry = nil
|
@currentEntry = nil
|
||||||
@compressor = NullCompressor
|
@compressor = NullCompressor.instance
|
||||||
end
|
end
|
||||||
|
|
||||||
def initNextEntry(entry, level = Zlib::DEFAULT_COMPRESSION)
|
def initNextEntry(entry, level = Zlib::DEFAULT_COMPRESSION)
|
||||||
|
@ -520,13 +522,15 @@ module Zip
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
def << (data)
|
|
||||||
@compressor << data
|
|
||||||
end
|
|
||||||
|
|
||||||
def finish
|
def finish
|
||||||
@compressor.finish
|
@compressor.finish
|
||||||
end
|
end
|
||||||
|
|
||||||
|
public
|
||||||
|
def << (data)
|
||||||
|
@compressor << data
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -538,22 +542,25 @@ module Zip
|
||||||
class PassThruCompressor < Compressor
|
class PassThruCompressor < Compressor
|
||||||
def initialize(outputStream)
|
def initialize(outputStream)
|
||||||
@outputStream = outputStream
|
@outputStream = outputStream
|
||||||
|
@crc = Zlib::crc32
|
||||||
@size = 0
|
@size = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
def << (data)
|
def << (data)
|
||||||
val = data.to_s
|
val = data.to_s
|
||||||
|
@crc = Zlib::crc32(val, @crc)
|
||||||
@size += val.size
|
@size += val.size
|
||||||
@outputStream << val
|
@outputStream << val
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :size
|
attr_reader :size, :crc
|
||||||
end
|
end
|
||||||
|
|
||||||
class NullCompressor < Compressor
|
class NullCompressor < Compressor
|
||||||
include Singleton
|
include Singleton
|
||||||
|
|
||||||
def << (data)
|
def << (data)
|
||||||
|
raise IOError, "closed stream"
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :size, :compressedSize
|
attr_reader :size, :compressedSize
|
||||||
|
@ -564,10 +571,12 @@ module Zip
|
||||||
@outputStream = outputStream
|
@outputStream = outputStream
|
||||||
@zlibDeflater = Zlib::Deflate.new(level, -Zlib::Deflate::MAX_WBITS)
|
@zlibDeflater = Zlib::Deflate.new(level, -Zlib::Deflate::MAX_WBITS)
|
||||||
@size = 0
|
@size = 0
|
||||||
|
@crc = Zlib::crc32
|
||||||
end
|
end
|
||||||
|
|
||||||
def << (data)
|
def << (data)
|
||||||
val = data.to_s
|
val = data.to_s
|
||||||
|
@crc = Zlib::crc32(val, @crc)
|
||||||
@size += val.size
|
@size += val.size
|
||||||
@outputStream << @zlibDeflater.deflate(data)
|
@outputStream << @zlibDeflater.deflate(data)
|
||||||
end
|
end
|
||||||
|
@ -578,7 +587,7 @@ module Zip
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :size
|
attr_reader :size, :crc
|
||||||
end
|
end
|
||||||
|
|
||||||
class ZipCentralDirectory
|
class ZipCentralDirectory
|
||||||
|
|
54
ziptest.rb
54
ziptest.rb
|
@ -551,7 +551,23 @@ class AbstractOutputStreamTest < RUNIT::TestCase
|
||||||
end
|
end
|
||||||
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
|
class PassThruCompressorTest < RUNIT::TestCase
|
||||||
|
include CrcTest
|
||||||
|
|
||||||
def test_size
|
def test_size
|
||||||
File.open("dummy.txt", "wb") {
|
File.open("dummy.txt", "wb") {
|
||||||
|file|
|
|file|
|
||||||
|
@ -573,9 +589,15 @@ class PassThruCompressorTest < RUNIT::TestCase
|
||||||
assert_equals(compressor.size, t1.size + t2.size + t3.size)
|
assert_equals(compressor.size, t1.size + t2.size + t3.size)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_crc
|
||||||
|
runCrcTest(PassThruCompressor)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class DeflaterTest < RUNIT::TestCase
|
class DeflaterTest < RUNIT::TestCase
|
||||||
|
include CrcTest
|
||||||
|
|
||||||
def test_outputOperator
|
def test_outputOperator
|
||||||
txt = loadFile("ziptest.rb")
|
txt = loadFile("ziptest.rb")
|
||||||
deflate(txt, "deflatertest.bin")
|
deflate(txt, "deflatertest.bin")
|
||||||
|
@ -608,8 +630,11 @@ class DeflaterTest < RUNIT::TestCase
|
||||||
txt = inflater.read
|
txt = inflater.read
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
|
def test_crc
|
||||||
|
runCrcTest(Deflater)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class ZipOutputStreamTest < RUNIT::TestCase
|
class ZipOutputStreamTest < RUNIT::TestCase
|
||||||
include AssertEntry
|
include AssertEntry
|
||||||
|
@ -634,18 +659,33 @@ class ZipOutputStreamTest < RUNIT::TestCase
|
||||||
assertTestZipContents(TEST_ZIP)
|
assertTestZipContents(TEST_ZIP)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_putOnClosedStream
|
|
||||||
fail "implement and expect ZipError"
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_writingToClosedStream
|
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
|
end
|
||||||
|
|
||||||
def test_cannotOpenFile
|
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
|
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)
|
def writeTestZip(zos)
|
||||||
TEST_ZIP.entryNames.each {
|
TEST_ZIP.entryNames.each {
|
||||||
|
|
Loading…
Reference in New Issue