У меня есть .gz файл, который содержит XML-документ. Кто-либо знает, как использовать 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 документ. Кто-либо знает, как я могу правильно сделать это?
Zlib::GzipReader
работает как большинство IO
-подобных классов в Ruby. У вас есть вызов open
, и когда вы передаете ему блок, блок получает IO
-подобный объект. Считайте, что это удобный способ делать что-то с файлом или ресурсом на время блока.
Но это означает, что в вашем примере gz
- это IO
-подобный объект, а не содержимое файла gzip, как вы ожидаете. Вам все равно нужно прочитать
из него, чтобы добраться до этого. Простейшим решением будет следующее:
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
За кулисами, это попытается использовать системный вызов sendfile
, доступный в некоторых специфических ситуациях в Linux. В противном случае он будет выполнять копирование в быстром C-коде блоками по 16 КБ за раз. Это я узнал из исходного кода Ruby 1.9.1.