2010-07-02 5 views
7

J'ai un fichier .gz qui contient un document XML. Est-ce que quelqu'un sait comment utiliser Zlib correctement? Jusqu'à présent, j'ai le code suivant:Zlib dans Ruby pour décompresser .gz

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() 
} 

Mais cela crée un document .xml vierge. Est-ce que quelqu'un sait comment je peux le faire correctement?

Répondre

22

Zlib::GzipReader fonctionne comme la plupart des classes IO-like en Ruby. Vous avez un appel open, et lorsque vous lui passez un bloc, le bloc recevra l'objet semblable à IO. Pensez que c'est une façon pratique de faire quelque chose avec un fichier ou une ressource pour la durée du bloc. Mais cela signifie que dans votre exemple, gz est un objet similaire à IO, et non le contenu du fichier gzip, comme vous le souhaitez. Vous avez encore besoin de read pour y arriver. La solution la plus simple serait alors:

g.write(gz.read) 

Notez que cela lire le contenu entier du non compressé gzip en mémoire.

Si tout ce que vous faites est de copier d'un fichier à un autre, vous pouvez utiliser la méthode IO.copy_stream plus efficace. Votre exemple pourrait alors ressembler à:

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 

Dans les coulisses, cela va essayer d'utiliser le sendfile syscall disponible dans certaines situations spécifiques sur Linux. Sinon, il effectuera la copie dans les blocs de code C rapide 16 Ko à la fois. C'est ce que j'ai appris du code source de Ruby 1.9.1.

2

Voici un Ruby one-liner (cd .git/premier et identifier chemin à un objet):

ruby -rzlib -e 'print Zlib::Inflate.new.inflate(STDIN.read)' < ./74/c757240ec596063af8cd273ebd9f67073e1208 
Questions connexes