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
За кулисами будет пытаться использовать системный вызов sendfile
, доступный в некоторых конкретных ситуациях в Linux. В противном случае он будет выполнять копирование в быстрых блоках кода C размером 16 КБ за раз. Это я узнал из исходного кода Ruby 1.9.1.