¿Cuáles son todas las formas comunes de leer un archivo en Ruby?


¿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?

 238
Author: dsg, 2011-04-05

8 answers

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 a open lo cierra por usted):

f = File.open("my/file/path", "r")
f.each_line do |line|
  puts line
end
f.close
 234
Author: fl00r,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-07 14:18:02

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 cierra automáticamente el archivo, por lo que no es necesario usar File.open con un bloque.

 270
Author: mckeed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-03 21:14:13

Tenga cuidado con los archivos de "sorber". Eso es cuando se lee 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 ponerlo en producción y de repente descubrir que está tratando de leer archivos que miden en gigabytes, y su host se está congelando mientras intenta leer y asignar memoria.

La E/S línea por línea es muy rápida, y casi siempre tan efectiva como sorber. Es sorprendentemente rápido realmente.

Me gusta usar:

IO.foreach("testfile") {|x| print "GOT ", x }

O

File.foreach('testfile') {|x| print "GOT", x }

El archivo hereda de IO, y foreach está en IO, por lo que puede usar cualquiera.

Tengo algunos puntos de referencia que muestran el impacto de intentar leer archivos grandes a través de read vs. E/S línea por línea en " ¿Por qué "sorber" un archivo no es una buena práctica?".

 198
Author: the Tin Man,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:33:25

Puede 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 desea acceder al controlador de archivo 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 los archivos binarios, puede especificar un separador nil y un tamaño de bloque, así:

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 un bloque, por ejemplo cuando procesa varios archivos simultáneamente. En ese caso, el archivo debe ser cerrado 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: File API y IO API .

 63
Author: Victor Klos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-11 20:35:14

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.

 23
Author: bta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-04 23:05:52
file_content = File.read('filename with extension');
puts file_content;

Http://www.ruby-doc.org/core-1.9.3/IO.html#method-c-read

 15
Author: Kumar Immanuel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-31 15:23:20

, normalmente hago esto:

open(path_in_string, &:read)

Esto le dará el texto completo como un objeto de cadena. Solo funciona bajo Ruby 1.9.

 9
Author: sawa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-03 21:14:49

Devuelve las últimas n líneas de tu_archivo.log or .txt

path = File.join(Rails.root, 'your_folder','your_file.log')

last_100_lines = `tail -n 100 #{path}`
 4
Author: Alex Danko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-06 13:11:17