You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 08:10:36