我有一个包含XML文档的.gz文件。有谁知道如何正确使用Zlib?到目前为止,我有以下代码:
require 'zlib'
Zlib::GzipReader.open('PRIDE_Exp_Complete_Ac_1015.xml.gz') { |gz|
g = File.new("PRIDE_Exp_Complete_Ac_1015.xml", "w")
g.write(gz)
g.close()
}
但是这会创建一个空白的.xml文档。有谁知道我怎么能正确地做到这一点?
答案 0 :(得分:23)
Zlib::GzipReader
的工作方式与大多数IO
类似 - 就像Ruby中的类一样。您有一个open
调用,当您向其传递一个块时,该块将收到类似IO
的对象。可以想象,这是在块的持续时间内对文件或资源执行某些操作的便捷方式。
但这意味着在您的示例中gz
是一个类似IO
的对象,实际上并不是gzip文件的内容,正如您所期望的那样。您仍然需要read
才能实现这一目标。最简单的解决方案是:
g.write(gz.read)
请注意,这会将未压缩 gzip的全部内容读入内存。
如果您真正要做的就是从一个文件复制到另一个文件,则可以使用效率更高的IO.copy_stream
方法。您的示例可能如下所示:
Zlib::GzipReader.open('PRIDE_Exp_Complete_Ac_1015.xml.gz') do | input_stream |
File.open("PRIDE_Exp_Complete_Ac_1015.xml", "w") do |output_stream|
IO.copy_stream(input_stream, output_stream)
end
end
在幕后,这将尝试使用Linux上某些特定情况下可用的sendfile
系统调用。否则,它将一次以快速C代码16KB块进行复制。我从Ruby 1.9.1源代码中学到了这一点。
答案 1 :(得分:2)
这是一个Ruby一行代码(cd .git / first并识别任何对象的路径):
ruby -rzlib -e 'print Zlib::Inflate.new.inflate(STDIN.read)' < ./74/c757240ec596063af8cd273ebd9f67073e1208