rubyzip 2.3.2加密zip时报IOError: not opened for writing求助
问题:rubyzip 2.3.2加密压缩场景报错
IOError: not opened for writing 原本项目使用zipruby,因依赖冲突迁移至rubyzip 2.3.2,其他场景适配正常,仅加密压缩zip文件时出现错误。
原zipruby代码
Zip::Archive.open('<zip-file-name>', Zip::CREATE) do |z| <list-of-strings>.each_with_index do |check, i| z.add_buffer 'r_%02d' % i, check end end Zip::Archive.encrypt('<zip-file-name>', '<password-string>')
尝试的rubyzip替代代码
buffer = Zip::OutputStream.write_buffer(::StringIO.new(''), Zip::TraditionalEncrypter.new('<password-string>')) do |output| <list-of-strings>.each_with_index do |check, i| output.put_next_entry('r_%02d' % i) output.write(check) end end File.open('<zip-file-name>', 'wb') {|f| f.write(buffer.string) }
错误信息
执行时在output.put_next_entry('r_%02d' % i)行抛出错误:
IOError: not opened for writing
回溯信息:
entry.rb 304 write(...) [GEM_ROOT]/gems/rubyzip-2.3.2/lib/zip/entry.rb:304:in `write' entry.rb 304 <<(...) [GEM_ROOT]/gems/rubyzip-2.3.2/lib/zip/entry.rb:304:in `<<' entry.rb 304 write_local_entry(...) [GEM_ROOT]/gems/rubyzip-2.3.2/lib/zip/entry.rb:304:in `write_local_entry' output_stream.rb 148 init_next_entry(...) [GEM_ROOT]/gems/rubyzip-2.3.2/lib/zip/output_stream.rb:148:in `init_next_entry' output_stream.rb 105 put_next_entry(...) [GEM_ROOT]/gems/rubyzip-2.3.2/lib/zip/output_stream.rb:105:in `put_next_entry'
解决方案
方案1:直接写入文件(推荐)
避免使用中间buffer,直接通过Zip::OutputStream.open写入目标文件,简化代码同时避免流状态问题:
Zip::OutputStream.open('<zip-file-name>', Zip::TraditionalEncrypter.new('<password-string>')) do |output| <list-of-strings>.each_with_index do |check, i| output.put_next_entry('r_%02d' % i) output.write(check) end end
方案2:修复buffer初始化问题
如果必须使用内存buffer,需将StringIO初始化改为二进制可写模式,原代码中::StringIO.new('')默认使用r+模式,会导致rubyzip写入时流状态异常:
buffer = Zip::OutputStream.write_buffer(::StringIO.new('', 'wb'), Zip::TraditionalEncrypter.new('<password-string>')) do |output| <list-of-strings>.each_with_index do |check, i| output.put_next_entry('r_%02d' % i) output.write(check) end end File.open('<zip-file-name>', 'wb') {|f| f.write(buffer.string) }
错误原因说明
rubyzip 2.3.2在处理加密压缩时,要求底层流处于可写状态。原代码中StringIO.new('')初始化的流默认是r+模式(读写但以初始字符串为内容),在写入加密条目时会触发流状态检查失败,改为wb模式(二进制可写)即可解决。
内容的提问来源于stack exchange,提问作者Pavit Kaur
相关产品推荐
相关产品推荐

