arreglos - file ruby
¿Cuáles son todas las formas comunes de leer un archivo en Ruby? (10)
¿Cuáles son todas las formas comunes de leer un archivo en Ruby?
Por ejemplo, aquí hay un método:
fileObj = File.new($fileName, "r")
while (line = fileObj.gets)
puts(line)
end
fileObj.close
Sé que Ruby es extremadamente flexible. ¿Cuáles son los beneficios / inconvenientes de cada enfoque?
Generalmente hago esto:
open(path_in_string, &:read)
Esto le dará todo el texto como un objeto de cadena. Funciona solo bajo Ruby 1.9.
La forma más fácil si el archivo no es demasiado largo es:
puts File.read(file_name)
De hecho, IO.read
o File.read
cierran automáticamente el archivo, por lo que no es necesario utilizar File.open
con un bloque.
Puedes leer el archivo de una vez:
content = File.readlines ''file.txt''
content.each_with_index{|line, i| puts "#{i+1}: #{line}"}
Cuando el archivo es grande, o puede ser grande, generalmente es mejor procesarlo línea por línea:
File.foreach( ''file.txt'' ) do |line|
puts line
end
A veces, usted desea acceder al identificador de archivos o controlar las lecturas usted mismo:
File.open( ''file.txt'' ) do |f|
loop do
break if not line = f.gets
puts "#{f.lineno}: #{line}"
end
end
En el caso de archivos binarios, puede especificar un separador nulo y un tamaño de bloque, como:
File.open(''file.bin'', ''rb'') do |f|
loop do
break if not buf = f.gets(nil, 80)
puts buf.unpack(''H*'')
end
end
Finalmente, puede hacerlo sin bloqueos, por ejemplo, al procesar varios archivos simultáneamente. En ese caso, el archivo debe cerrarse explícitamente (mejorado según el comentario de @antinome):
begin
f = File.open ''file.txt''
while line = f.gets
puts line
end
ensure
f.close
end
Referencias: API de archivos y la API de IO .
Tenga cuidado con los archivos "slurping". Ahí es cuando lees todo el archivo en la memoria a la vez.
El problema es que no se escala bien. Podría estar desarrollando código con un archivo de tamaño razonable, luego póngalo en producción y de repente descubra que está intentando leer archivos que miden en gigabytes, y su host se está congelando cuando intenta leer y asignar memoria.
La E / S línea por línea es muy rápida, y casi siempre tan efectiva como el sorbido. Es sorprendentemente rápido en realidad.
Me gusta usar:
IO.foreach("testfile") {|x| print "GOT ", x }
o
File.foreach(''testfile'') {|x| print "GOT", x }
El archivo se hereda de IO y foreach
está en IO, por lo que puede usar cualquiera de los dos.
Tengo algunos puntos de referencia que muestran el impacto de tratar de leer archivos grandes a través de E / S de read
frente a línea en " ¿Por qué es" una buena práctica " no es una buena práctica? ".
Un método simple es usar readlines
:
my_array = IO.readlines(''filename.txt'')
Cada línea en el archivo de entrada será una entrada en la matriz. El método se encarga de abrir y cerrar el archivo por usted.
Una forma aún más eficiente es la transmisión al pedir al núcleo del sistema operativo que abra un archivo, y luego leer los bytes poco a poco. Al leer un archivo por línea en Ruby, los datos se toman del archivo de 512 bytes a la vez y se dividen en "líneas" después de eso.
Al almacenar en búfer el contenido del archivo, el número de llamadas de E / S se reduce mientras se divide el archivo en partes lógicas.
Ejemplo:
Agrega esta clase a tu aplicación como un objeto de servicio:
class MyIO
def initialize(filename)
fd = IO.sysopen(filename)
@io = IO.new(fd)
@buffer = ""
end
def each(&block)
@buffer << @io.sysread(512) until @buffer.include?($/)
line, @buffer = @buffer.split($/, 2)
block.call(line)
each(&block)
rescue EOFError
@io.close
end
end
Llámalo y pasa el :each
método un bloque:
filename = ''./somewhere/large-file-4gb.txt''
MyIO.new(filename).each{|x| puts x }
Lea sobre esto aquí en este post detallado:
devuelve las últimas n líneas desde tu_archivo.log o .txt
path = File.join(Rails.root, ''your_folder'',''your_file.log'')
last_100_lines = `tail -n 100 #{path}`
File.open("my/file/path", "r") do |f|
f.each_line do |line|
puts line
end
end
# File is closed automatically at end of block
También es posible cerrar explícitamente el archivo después de lo anterior (pasar un bloque para open
cierra por usted):
f = File.open("my/file/path", "r")
f.each_line do |line|
puts line
end
f.close
content = `cat file`
Creo que este método es el más "raro". Tal vez sea un poco complicado, pero funciona si se instala cat
.
file_content = File.read(''filename with extension'');
puts file_content;