如何用rubyzip读取压缩包中.xlsx文件数据,无需临时解压?
解决Ruby中从Zip包内读取XLSX数据(无需临时解压)
针对Creek的解决方案
Creek支持直接传入二进制IO对象,无需提前保存文件。只需过滤出.xlsx后缀的entry,将其输入流以二进制模式传入即可:
require 'creek' require 'zip' Zip::File.open(file_path) do |zip_file| zip_file.each do |entry| next unless entry.name.end_with?('.xlsx') # 获取二进制输入流,避免编码乱码 stream = entry.get_input_stream stream.set_encoding(Encoding::BINARY) # 用Creek解析流中的XLSX内容 creek = Creek::Book.new stream creek.sheets.each do |sheet| sheet.rows.each do |row| # 按需处理每行数据 puts row.inspect end end end end
针对Roo的解决方案
Roo的Excelx类可接收IO对象,但需要用StringIO包装二进制内容来规避编码问题:
require 'roo' require 'zip' require 'stringio' Zip::File.open(file_path) do |zip_file| zip_file.each do |entry| next unless entry.name.end_with?('.xlsx') # 读取二进制内容并包装成StringIO xlsx_content = entry.get_input_stream.read.force_encoding(Encoding::BINARY) xlsx_io = StringIO.new(xlsx_content) # 用Roo解析IO中的XLSX,大文件推荐用streaming模式 xlsx = Roo::Excelx.new(xlsx_io) xlsx.sheets.each do |sheet_name| xlsx.sheet(sheet_name).each_row_streaming do |row| # 按需处理行数据 puts row.map(&:value).inspect end end end end
核心注意事项
- 必须确保流以二进制编码处理,这是解决乱码问题的关键。
- 处理大文件时,优先使用Roo的
each_row_streaming或Creek的rows方法,避免一次性加载全量数据到内存。 - 如果你的
file_path本身就是XLSX文件(而非包含XLSX的Zip包),无需手动用rubyzip处理——Roo和Creek内部已经实现了XLSX的Zip结构解析,直接调用Roo::Excelx.new(file_path)或Creek::Book.new(file_path)即可。
内容的提问来源于stack exchange,提问作者sombersushi
相关产品推荐
相关产品推荐

