2008-09-25 21 views
256

Necesito una manera fácil de tomar un archivo tar y convertirlo en una cadena (y viceversa). ¿Hay alguna manera de hacer esto en Ruby? Mi mejor intento fue la siguiente:Lea el archivo binario como una cadena en Ruby

file = File.open("path-to-file.tar.gz") 
contents = "" 
file.each {|line| 
    contents << line 
} 

pensé que sería suficiente para convertirlo en una cadena, pero cuando trato de escribir de nuevo fuera así ...

newFile = File.open("test.tar.gz", "w") 
newFile.write(contents) 

ISN es el mismo archivo. Haciendo ls -l muestra que los archivos son de diferentes tamaños, aunque son bastante cercanos (y al abrir el archivo se revela que la mayoría de los contenidos están intactos). ¿Hay un pequeño error que estoy cometiendo o una manera completamente diferente (pero factible) de lograr esto?

+3

Eso es un archivo tar comprimido con gzip (espero). No hay "líneas" Pls aclara lo que estás tratando de lograr. –

+0

¿Estás tratando de ver los datos comprimidos o el contenido sin comprimir? –

+0

para que los caracteres en una secuencia de datos comprimidos tengan aproximadamente 1 en 256 posibilidades de aterrizar en "\ n" definiendo el final de una línea, y eso está bien si no espera "\ r" también, vea mi respuesta debajo de – Purfideas

Respuesta

380

En primer lugar, debe abrir el archivo como un archivo binario. Luego puede leer todo el archivo, en un solo comando.

file = File.open("path-to-file.tar.gz", "rb") 
contents = file.read 

Eso le dará el archivo completo en una cadena.

Después de eso, es probable que desee file.close. Si no lo hace, file no se cerrará hasta que se recoja la basura, por lo que sería un desperdicio leve de recursos del sistema mientras está abierto.

+92

One-liner: File.open ("ruta-a-archivo.tar.gz", "rb"). Read – Nobu

+22

El indicador binario solo es relevante en Windows, y esto deja el descriptor de archivo abierto. File.read (...) es mejor. –

+0

¿Hay algo de malo con tantas personas mirando esto y copiando pegándolo como una solución de una sola línea (como tantas cosas en stackoverflow)? Después de todo, funciona, y el nombre de estas funciones era solo una elección arbitraria de los diseñadores de la biblioteca de rubíes. Si solo tuviéramos algún lenguaje con sinónimos ... que de alguna manera todavía sepa exactamente lo que queremos en casos extremos/instancias ambiguas. Entonces simplemente voy a 'contents = (contenido del archivo" ruta a archivo.txt "como cadena)'. – masterxilo

4

Probablemente pueda codificar el archivo tar en Base64. Base 64 le dará una representación ASCII pura del archivo que puede almacenar en un archivo de texto sin formato. Luego puede recuperar el archivo tar decodificando el texto.

haces algo como:

require 'base64' 

file_contents = Base64.encode64(tar_file_data) 

tienen mirada en la base 64 Rubydocs para tener una mejor idea.

+0

¡Genial, parece que también funcionará! Tendré que echarle un vistazo si por alguna razón, leer el contenido binario se agrisa. –

16

en el sistema operativo x estos son los mismos para mí ... ¿podría esto ser más "\ r" en windows?

en ningún caso se le puede mejor con:

contents = File.read("e.tgz") 
newFile = File.open("ee.tgz", "w") 
newFile.write(contents) 
+0

'File.read (" e.txt ")' funciona muy bien para mí. – bean5

+0

Parece la solución más simple. – Dishcandanty

113

Para evitar dejar el archivo abierto, es mejor pasar un bloque a File.open. De esta manera, el archivo se cerrará después de que se ejecute el bloque.

contents = File.open('path-to-file.tar.gz', 'rb') { |f| f.read } 
+9

Esta es una mejor respuesta que la de David Nehme porque los descriptores de archivos son un recurso de sistema finito y agotarlos es un problema común que se puede evitar fácilmente. –

237

Si necesita modo binario, tendrá que hacerlo de la manera difícil:

s = File.open(filename, 'rb') { |f| f.read } 

Si no es así, más corto y más dulce es:

s = IO.read(filename) 
+0

¿Cómo es 'IO.read' no binario-seguro? –

+0

En ruby ​​1.9.3+, IO.read le dará una cadena marcada con la codificación en Encoding.default_external. Creo que (?) Los bytes serán como estaban en el archivo, por lo que no es exactamente "no binario-seguro", pero tendrás que etiquetarlo con la codificación binaria si eso es lo que quieres. – jrochkind

17

cómo sobre algunos abiertos/cierre de seguridad.

string = File.open('file.txt', 'rb') { |file| file.read } 
+0

¿por qué no un .close explícito? Tal como en el archivo OP.close cuando se hace? – Joshua

+2

File.open() {| archivo | bloque} se cierra automáticamente cuando termina el bloque. http://ruby-doc.org/core-1.9.3/File.html#method-c-open – Alex

+12

Esto es idéntico a [respuesta de Aaron Hinni] (http://stackoverflow.com/a/131096/ 215168) que se publicó en 2008 (excepto que no usa el archivo de OP y los nombres de variables) ... –

0

Si puede codificar el archivo tar de base 64 (y almacenarla en un archivo de texto plano), puede utilizar

File.open("my_tar.txt").each {|line| puts line} 

o

File.new("name_file.txt", "r").each {|line| puts line} 

para imprimir cada una (texto) línea en el cmd.

5

Rubí tiene lectura binaria

data = IO.binread(path/filaname) 

o si es menos de Rubí 1.9.2

data = IO.read(path/file) 
Cuestiones relacionadas