diff --git a/lib/xlsxtream/io/rubyzip.rb b/lib/xlsxtream/io/rubyzip.rb
index f706366..f60ef4f 100644
--- a/lib/xlsxtream/io/rubyzip.rb
+++ b/lib/xlsxtream/io/rubyzip.rb
@@ -1,12 +1,16 @@
require "zip"
+require "xlsxtream/errors"
module Xlsxtream
module IO
class RubyZip
- def initialize(path_or_io)
- @stream = path_or_io.respond_to? :reopen
- path_or_io.binmode if path_or_io.respond_to? :binmode
- @zos = Zip::OutputStream.new(path_or_io, @stream)
+ def initialize(io)
+ unless io.respond_to? :pos and io.respond_to? :pos=
+ raise Error, 'IO is not seekable'
+ end
+ io.binmode if io.respond_to? :binmode
+ stream = true
+ @zos = Zip::OutputStream.new(io, stream)
end
def <<(data)
@@ -20,7 +24,6 @@ def add_file(path)
def close
os = @zos.close_buffer
os.flush if os.respond_to? :flush
- os.close if !@stream and os.respond_to? :close
end
end
end
diff --git a/lib/xlsxtream/workbook.rb b/lib/xlsxtream/workbook.rb
index 0c6cd31..d948a5b 100644
--- a/lib/xlsxtream/workbook.rb
+++ b/lib/xlsxtream/workbook.rb
@@ -1,12 +1,9 @@
# encoding: utf-8
-require "stringio"
require "xlsxtream/errors"
require "xlsxtream/xml"
require "xlsxtream/shared_string_table"
require "xlsxtream/workbook"
require "xlsxtream/io/rubyzip"
-require "xlsxtream/io/directory"
-require "xlsxtream/io/stream"
module Xlsxtream
class Workbook
@@ -22,8 +19,8 @@ class Workbook
class << self
- def open(data = nil, options = {})
- workbook = new(data, options)
+ def open(output = nil, options = {})
+ workbook = new(output, options)
if block_given?
begin
yield workbook
@@ -37,10 +34,16 @@ def open(data = nil, options = {})
end
- def initialize(data = nil, options = {})
+ def initialize(output = nil, options = {})
+ output ||= StringIO.new
@options = options
io_wrapper = options[:io_wrapper] || IO::RubyZip
- @io = io_wrapper.new(data || StringIO.new)
+ if output.is_a?(String) || !output.respond_to?(:<<)
+ @file = File.open(output, 'wb')
+ @io = io_wrapper.new(@file)
+ else
+ @io = io_wrapper.new(output)
+ end
@sst = SharedStringTable.new
@worksheets = Hash.new { |hash, name| hash[name] = hash.size + 1 }
end
@@ -74,6 +77,7 @@ def close
write_root_rels
write_content_types
@io.close
+ @file.close if @file
nil
end
diff --git a/test/xlsxtream/io/directory_test.rb b/test/xlsxtream/io/directory_test.rb
new file mode 100644
index 0000000..6c96c2e
--- /dev/null
+++ b/test/xlsxtream/io/directory_test.rb
@@ -0,0 +1,32 @@
+require 'test_helper'
+require 'xlsxtream/io/directory'
+require 'pathname'
+
+module Xlsxtream
+ module IO
+ class DirectoryTest < Minitest::Test
+
+ def test_writes_of_multiple_files
+ Dir.mktmpdir do |dir|
+ io = Xlsxtream::IO::Directory.new(dir)
+ io.add_file("book1.xml")
+ io << ''
+ io.add_file("book2.xml")
+ io << ''
+ io << ''
+ io.add_file("empty.txt")
+ io.add_file("another.xml")
+ io << ''
+ io.close
+
+ dir = Pathname(dir)
+ assert_equal '', dir.join('empty.txt').read
+ assert_equal '', dir.join('book1.xml').read
+ assert_equal '', dir.join('book2.xml').read
+ assert_equal '', dir.join('another.xml').read
+ end
+
+ end
+ end
+ end
+end
diff --git a/test/xlsxtream/io/hash_test.rb b/test/xlsxtream/io/hash_test.rb
new file mode 100644
index 0000000..efbd17d
--- /dev/null
+++ b/test/xlsxtream/io/hash_test.rb
@@ -0,0 +1,30 @@
+require 'test_helper'
+require 'xlsxtream/io/hash'
+
+module Xlsxtream
+ module IO
+ class HashTest < Minitest::Test
+
+ def test_writes_of_multiple_files
+ buffer = StringIO.new
+
+ io = Xlsxtream::IO::Hash.new(buffer)
+ io.add_file("book1.xml")
+ io << ''
+ io.add_file("book2.xml")
+ io << ''
+ io << ''
+ io.add_file("empty.txt")
+ io.add_file("another.xml")
+ io << ''
+ io.close
+
+ file_contents = io.to_h
+ assert_equal '', file_contents['empty.txt']
+ assert_equal '', file_contents['book1.xml']
+ assert_equal '', file_contents['book2.xml']
+ assert_equal '', file_contents['another.xml']
+ end
+ end
+ end
+end
diff --git a/test/xlsxtream/io/rubyzip_test.rb b/test/xlsxtream/io/rubyzip_test.rb
new file mode 100644
index 0000000..be8666c
--- /dev/null
+++ b/test/xlsxtream/io/rubyzip_test.rb
@@ -0,0 +1,40 @@
+require 'test_helper'
+require 'xlsxtream/io/rubyzip'
+require 'zip'
+
+module Xlsxtream
+ module IO
+ class RubyZipTest < Minitest::Test
+
+ def test_writes_of_multiple_files
+ zip_buf = Tempfile.new('ztio-test')
+
+ io = Xlsxtream::IO::RubyZip.new(zip_buf)
+ io.add_file("book1.xml")
+ io << ''
+ io.add_file("book2.xml")
+ io << ''
+ io << ''
+ io.add_file("empty.txt")
+ io.add_file("another.xml")
+ io << ''
+ io.close
+
+ zip_buf.rewind
+
+ file_contents = {}
+ ::Zip::File.open(zip_buf) do |zip_file|
+ zip_file.each do |entry|
+ file_contents[entry.name] = entry.get_input_stream.read
+ end
+ end
+ assert_equal '', file_contents['empty.txt']
+ assert_equal '', file_contents['book1.xml']
+ assert_equal '', file_contents['book2.xml']
+ assert_equal '', file_contents['another.xml']
+ ensure
+ zip_buf.close! if zip_buf
+ end
+ end
+ end
+end
diff --git a/test/xlsxtream/io/stream_test.rb b/test/xlsxtream/io/stream_test.rb
new file mode 100644
index 0000000..aa756ed
--- /dev/null
+++ b/test/xlsxtream/io/stream_test.rb
@@ -0,0 +1,36 @@
+require 'test_helper'
+require 'xlsxtream/io/stream'
+
+module Xlsxtream
+ module IO
+ class StreamTest < Minitest::Test
+
+ def test_writes_of_multiple_files
+ buffer = StringIO.new
+
+ io = Xlsxtream::IO::Stream.new(buffer)
+ io.add_file("book1.xml")
+ io << ''
+ io.add_file("book2.xml")
+ io << ''
+ io << ''
+ io.add_file("empty.txt")
+ io.add_file("another.xml")
+ io << ''
+ io.close
+
+ file_contents = buffer.string
+ assert_equal <<-EOF, file_contents
+book1.xml
+
+book2.xml
+
+empty.txt
+
+another.xml
+
+EOF
+ end
+ end
+ end
+end
diff --git a/test/xlsxtream/workbook_test.rb b/test/xlsxtream/workbook_test.rb
index d5ce02a..460ea98 100644
--- a/test/xlsxtream/workbook_test.rb
+++ b/test/xlsxtream/workbook_test.rb
@@ -1,10 +1,27 @@
require 'test_helper'
+require 'tempfile'
require 'xlsxtream/workbook'
require 'xlsxtream/io/hash'
module Xlsxtream
class WorksheetTest < Minitest::Test
+ def test_workbook_from_path
+ tempfile = Tempfile.new('xlsxtream')
+ Workbook.open(tempfile.path) {}
+ refute_equal 0, tempfile.size
+ ensure
+ tempfile.close! if tempfile
+ end
+
+ def test_workbook_from_io
+ tempfile = Tempfile.new('xlsxtream')
+ Workbook.open(tempfile) {}
+ refute_equal 0, tempfile.size
+ ensure
+ tempfile.close! if tempfile
+ end
+
def test_empty_workbook
iow_spy = io_wrapper_spy
Workbook.open(nil, :io_wrapper => iow_spy) {}