iostreams 0.20.1 → 0.20.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d2c3b941a898cf14f2e8d5ac430f55efc602126f0d2e339014cb3de97d7c9233
4
- data.tar.gz: e5745a12f24746ecf624627ac45e900251b0c3b83b109d7f18c04ffaf4efeba5
3
+ metadata.gz: f09dde2bcb517dd7c24e6bdf7bdfcfe313b2c5a17f3c8b1ac6caf850d1057364
4
+ data.tar.gz: 8886732d0a04007205ac6b0f76aede0efc4617dc5fae51f06d9d9a4f5420fdb9
5
5
  SHA512:
6
- metadata.gz: ae879c20c587da2b9a2c5ae36a0488346b49f11470bd812640d6ccda161434221b98cdb65c5d7cc2988492621822a4e301665033e94207f90b323299b2e0fc24
7
- data.tar.gz: a325782b46feeaf314a94f758be89d02b006fabfe824c91b2ac17309841980cab4cb9129318040426d9d6582bff6dd7345bc40f9234b0cd2e89c0d5555948335
6
+ metadata.gz: 894766215e6e1e6d942e3afbc5a1c797dbf5abf7a885a0a63e9fb29985e77f9ff84449d53f147484b0edb041e6bd89094b2824e3144ba0020cbadb8dc9fb9943
7
+ data.tar.gz: 69806e7e4ff2cd9184c63a906ca25d44a69003c52e477fe96fa563bc99590f117b0701e0231cf8543e617cb31f63c0ed615a2d54ff8d757e00eb1e420d637d1d
@@ -1,3 +1,3 @@
1
1
  module IOStreams
2
- VERSION = '0.20.1'
2
+ VERSION = '0.20.2'
3
3
  end
@@ -3,7 +3,12 @@ module IOStreams
3
3
  class Reader
4
4
  # Read from a zip file or stream, decompressing the contents as it is read
5
5
  # The input stream from the first file found in the zip file is passed
6
- # to the supplied block
6
+ # to the supplied block.
7
+ #
8
+ # Parameters:
9
+ # entry_file_name: [String]
10
+ # Name of the file within the Zip file to read.
11
+ # Default: Read the first file found in the zip file.
7
12
  #
8
13
  # Example:
9
14
  # IOStreams::Zip::Reader.open('abc.zip') do |io_stream|
@@ -12,58 +17,65 @@ module IOStreams
12
17
  # puts data
13
18
  # end
14
19
  # end
15
- def self.open(file_name_or_io, _ = nil, &block)
16
- if !defined?(JRuby) && !defined?(::Zip)
17
- # MRI needs Ruby Zip, since it only has native support for GZip
18
- begin
19
- require 'zip'
20
- rescue LoadError => exc
21
- raise(LoadError, "Install gem 'rubyzip' to read and write Zip files: #{exc.message}")
22
- end
23
- end
24
-
20
+ def self.open(file_name_or_io, entry_file_name: nil, &block)
25
21
  # File name supplied
26
- return read_file(file_name_or_io, &block) unless IOStreams.reader_stream?(file_name_or_io)
22
+ return read_file(file_name_or_io, entry_file_name, &block) unless IOStreams.reader_stream?(file_name_or_io)
27
23
 
28
- # ZIP can only work against a file, not a stream, so create temp file.
24
+ # Ruby ZIP gem uses `#seek` so can only work against a file, not a stream, so create temp file.
25
+ # JRuby ZIP requires an InputStream.
29
26
  IOStreams::File::Path.temp_file_name('iostreams_zip') do |temp_file_name|
30
27
  IOStreams.copy(file_name_or_io, temp_file_name, target_options: {streams: []})
31
- read_file(temp_file_name, &block)
28
+ read_file(temp_file_name, entry_file_name, &block)
32
29
  end
33
30
  end
34
31
 
35
32
  if defined?(JRuby)
36
33
  # Java has built-in support for Zip files
37
- def self.read_file(file_name, &block)
34
+ def self.read_file(file_name, entry_file_name)
38
35
  fin = Java::JavaIo::FileInputStream.new(file_name)
39
36
  zin = Java::JavaUtilZip::ZipInputStream.new(fin)
40
- zin.get_next_entry
41
- block.call(zin.to_io)
37
+
38
+ get_entry(zin, entry_file_name) ||
39
+ raise(Java::JavaUtilZip::ZipException.new("File #{entry_file_name} not found within zip file."))
40
+
41
+ yield(zin.to_io)
42
42
  ensure
43
43
  zin.close if zin
44
44
  fin.close if fin
45
45
  end
46
46
 
47
47
  else
48
-
49
48
  # Read from a zip file or stream, decompressing the contents as it is read
50
49
  # The input stream from the first file found in the zip file is passed
51
50
  # to the supplied block
52
- def self.read_file(file_name, &block)
53
- begin
54
- zin = ::Zip::InputStream.new(file_name)
55
- zin.get_next_entry
56
- block.call(zin)
57
- ensure
51
+ def self.read_file(file_name, entry_file_name)
52
+ if !defined?(::Zip)
53
+ # MRI needs Ruby Zip, since it only has native support for GZip
58
54
  begin
59
- zin.close if zin
60
- rescue IOError
61
- # Ignore file already closed errors since Zip::InputStream
62
- # does not have a #closed? method
55
+ require 'zip'
56
+ rescue LoadError => exc
57
+ raise(LoadError, "Install gem 'rubyzip' to read and write Zip files: #{exc.message}")
63
58
  end
64
59
  end
60
+
61
+ ::Zip::InputStream.open(file_name) do |zin|
62
+ get_entry(zin, entry_file_name) ||
63
+ raise(::Zip::EntryNameError, "File #{entry_file_name} not found within zip file.")
64
+ yield(zin)
65
+ end
65
66
  end
67
+ end
66
68
 
69
+ def self.get_entry(zin, entry_file_name)
70
+ if entry_file_name.nil?
71
+ zin.get_next_entry
72
+ return true
73
+ end
74
+
75
+ while entry = zin.get_next_entry
76
+ return true if entry.name == entry_file_name
77
+ end
78
+ false
67
79
  end
68
80
  end
69
81
  end
Binary file
Binary file
@@ -30,6 +30,22 @@ class IOStreamsTest < Minitest::Test
30
30
  bad_data.gsub("\xE9".b, '').gsub("\x07", '')
31
31
  end
32
32
 
33
+ let :multiple_zip_file_name do
34
+ File.join(File.dirname(__FILE__), 'files', 'multiple_files.zip')
35
+ end
36
+
37
+ let :zip_gz_file_name do
38
+ File.join(File.dirname(__FILE__), 'files', 'text.zip.gz')
39
+ end
40
+
41
+ let :contents_test_txt do
42
+ File.read(File.join(File.dirname(__FILE__), 'files', 'text.txt'))
43
+ end
44
+
45
+ let :contents_test_json do
46
+ File.read(File.join(File.dirname(__FILE__), 'files', 'test.json'))
47
+ end
48
+
33
49
  after do
34
50
  temp_file.delete
35
51
  end
@@ -124,5 +140,20 @@ class IOStreamsTest < Minitest::Test
124
140
  end
125
141
  end
126
142
 
143
+ describe '.reader' do
144
+ it 'reads a zip file' do
145
+ result = IOStreams.reader(multiple_zip_file_name, streams: {zip: {entry_file_name: 'test.json'}}) do |io|
146
+ io.read
147
+ end
148
+ assert_equal contents_test_json, result
149
+ end
150
+
151
+ it 'reads a zip file from within a gz file' do
152
+ result = IOStreams.reader(zip_gz_file_name) do |io|
153
+ io.read
154
+ end
155
+ assert_equal contents_test_txt, result
156
+ end
157
+ end
127
158
  end
128
159
  end
@@ -0,0 +1,25 @@
1
+ # The miminum methods that any IOStreams Reader must implement.
2
+ class MinimalFileReader
3
+ def self.open(file_name)
4
+ io = new(file_name)
5
+ yield(io)
6
+ ensure
7
+ io.close if io
8
+ end
9
+
10
+ def initialize(file_name)
11
+ @file = File.open(file_name)
12
+ end
13
+
14
+ def read(size = nil, outbuf = nil)
15
+ @file.read(size, outbuf)
16
+ end
17
+
18
+ def close
19
+ @file.close
20
+ end
21
+
22
+ def closed?
23
+ @file.closed
24
+ end
25
+ end
@@ -1,4 +1,5 @@
1
1
  require_relative 'test_helper'
2
+ require_relative 'minimal_file_reader'
2
3
  require 'zip'
3
4
 
4
5
  class ZipReaderTest < Minitest::Test
@@ -7,20 +8,46 @@ class ZipReaderTest < Minitest::Test
7
8
  File.join(File.dirname(__FILE__), 'files', 'text.zip')
8
9
  end
9
10
 
11
+ let :multiple_zip_file_name do
12
+ File.join(File.dirname(__FILE__), 'files', 'multiple_files.zip')
13
+ end
14
+
15
+ let :contents_test_txt do
16
+ File.read(File.join(File.dirname(__FILE__), 'files', 'text.txt'))
17
+ end
18
+
19
+ let :contents_test_json do
20
+ File.read(File.join(File.dirname(__FILE__), 'files', 'test.json'))
21
+ end
22
+
10
23
  let :decompressed do
11
24
  Zip::File.open(file_name) { |zip_file| zip_file.first.get_input_stream.read }
12
25
  end
13
26
 
14
27
  describe '.open' do
15
- it 'file' do
28
+ it 'reads the first file' do
16
29
  result = IOStreams::Zip::Reader.open(file_name) do |io|
17
30
  io.read
18
31
  end
19
32
  assert_equal decompressed, result
20
33
  end
21
34
 
22
- it 'stream' do
23
- result = File.open(file_name) do |file|
35
+ it 'reads entry within zip file' do
36
+ result = IOStreams::Zip::Reader.open(multiple_zip_file_name, entry_file_name: 'text.txt') do |io|
37
+ io.read
38
+ end
39
+ assert_equal contents_test_txt, result
40
+ end
41
+
42
+ it 'reads another entry within zip file' do
43
+ result = IOStreams::Zip::Reader.open(multiple_zip_file_name, entry_file_name: 'test.json') do |io|
44
+ io.read
45
+ end
46
+ assert_equal contents_test_json, result
47
+ end
48
+
49
+ it 'reads from a stream' do
50
+ result = MinimalFileReader.open(file_name) do |file|
24
51
  IOStreams::Zip::Reader.open(file) do |io|
25
52
  io.read
26
53
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iostreams
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.20.1
4
+ version: 0.20.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Reid Morrison
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-24 00:00:00.000000000 Z
11
+ date: 2019-09-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -89,6 +89,7 @@ files:
89
89
  - test/file_reader_test.rb
90
90
  - test/file_writer_test.rb
91
91
  - test/files/embedded_lines_test.csv
92
+ - test/files/multiple_files.zip
92
93
  - test/files/spreadsheet.xlsx
93
94
  - test/files/test.csv
94
95
  - test/files/test.json
@@ -97,6 +98,7 @@ files:
97
98
  - test/files/text.txt.gz
98
99
  - test/files/text.txt.gz.zip
99
100
  - test/files/text.zip
101
+ - test/files/text.zip.gz
100
102
  - test/files/unclosed_quote_test.csv
101
103
  - test/gzip_reader_test.rb
102
104
  - test/gzip_writer_test.rb
@@ -104,6 +106,7 @@ files:
104
106
  - test/io_streams_test.rb
105
107
  - test/line_reader_test.rb
106
108
  - test/line_writer_test.rb
109
+ - test/minimal_file_reader.rb
107
110
  - test/path_test.rb
108
111
  - test/pgp_reader_test.rb
109
112
  - test/pgp_test.rb
@@ -147,6 +150,7 @@ test_files:
147
150
  - test/base_path_test.rb
148
151
  - test/line_reader_test.rb
149
152
  - test/xlsx_reader_test.rb
153
+ - test/minimal_file_reader.rb
150
154
  - test/row_writer_test.rb
151
155
  - test/zip_reader_test.rb
152
156
  - test/bzip2_writer_test.rb
@@ -166,11 +170,13 @@ test_files:
166
170
  - test/files/embedded_lines_test.csv
167
171
  - test/files/test.csv
168
172
  - test/files/test.json
173
+ - test/files/text.zip.gz
169
174
  - test/files/unclosed_quote_test.csv
170
175
  - test/files/text.txt.bz2
171
176
  - test/files/text.txt.gz.zip
172
177
  - test/files/text.txt.gz
173
178
  - test/files/text.txt
179
+ - test/files/multiple_files.zip
174
180
  - test/gzip_reader_test.rb
175
181
  - test/encode_reader_test.rb
176
182
  - test/test_helper.rb