web-dev-qa-db-fra.com

Quels sont les moyens courants de lire un fichier en Ruby?

Quels sont les moyens courants de lire un fichier en Ruby?

Par exemple, voici une méthode:

fileObj = File.new($fileName, "r")
while (line = fileObj.gets)
  puts(line)
end
fileObj.close

Je sais que Ruby est extrêmement flexible. Quels sont les avantages/inconvénients de chaque approche?

252
dsg
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

Il est également possible de fermer explicitement le fichier après comme ci-dessus (passer un bloc à open le ferme pour vous):

f = File.open("my/file/path", "r")
f.each_line do |line|
  puts line
end
f.close
240
fl00r

Le moyen le plus simple si le fichier n'est pas trop long est:

puts File.read(file_name)

En effet, IO.read ou File.read ferme automatiquement le fichier, il n'est donc pas nécessaire d'utiliser File.open avec un bloc.

286
mckeed

Méfiez-vous des fichiers "glissants". C'est à ce moment-là que vous lisez tout le fichier en mémoire en une fois. 

Le problème est que cela ne va pas bien. Vous pourriez développer du code avec un fichier de taille raisonnable, puis le mettre en production et trouver soudainement que vous essayez de lire des fichiers mesurant en gigaoctets et que votre hôte se bloque alors qu'il tente de lire et d'allouer de la mémoire. 

Les E/S ligne par ligne sont très rapides et presque toujours aussi efficaces que le slurping. C'est étonnamment rapide en fait.

J'aime utiliser:

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

ou

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

Le fichier hérite d'IO et foreach est dans IO, vous pouvez donc utiliser l'un ou l'autre.

J'ai quelques points de repère montrant l'impact d'essayer de lire de gros fichiers via read contre des entrées/sorties ligne par ligne à " Pourquoi" extraire "un fichier n'est pas une bonne pratique? ".

206
the Tin Man

Vous pouvez lire le fichier en une fois:

content = File.readlines 'file.txt'
content.each_with_index{|line, i| puts "#{i+1}: #{line}"}

Lorsque le fichier est volumineux, ou peut être volumineux, il est généralement préférable de le traiter ligne par ligne:

File.foreach( 'file.txt' ) do |line|
  puts line
end

Parfois, vous souhaitez cependant accéder au descripteur de fichier ou contrôler vous-même les lectures:

File.open( 'file.txt' ) do |f|
  loop do
    break if not line = f.gets
    puts "#{f.lineno}: #{line}"
  end
end

Dans le cas de fichiers binaires, vous pouvez spécifier un séparateur nul et une taille de bloc, comme suit:

File.open('file.bin', 'rb') do |f|
  loop do
    break if not buf = f.gets(nil, 80)
    puts buf.unpack('H*')
  end
end

Enfin, vous pouvez le faire sans blocage, par exemple lors du traitement simultané de plusieurs fichiers. Dans ce cas, le fichier doit être explicitement fermé (amélioré conformément au commentaire de @antinome):

begin
  f = File.open 'file.txt'
  while line = f.gets
    puts line
  end
ensure
  f.close
end

Références: API de fichier et l'API IO .

65
Victor Klos

Une méthode simple consiste à utiliser readlines :

my_array = IO.readlines('filename.txt')

Chaque ligne du fichier d’entrée sera une entrée du tableau. La méthode gère l’ouverture et la fermeture du fichier pour vous.

23
bta
file_content = File.read('filename with extension');
puts file_content;

http://www.Ruby-doc.org/core-1.9.3/IO.html#method-c-read

16
Kumar Immanuel

Je fais habituellement ceci:

open(path_in_string, &:read)

Cela vous donnera le texte entier en tant qu'objet chaîne. Cela ne fonctionne que sous Ruby 1.9.

9
sawa

retourne les dernières n lignes de your_file.log ou .txt

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

last_100_lines = `tail -n 100 #{path}`
4
Alex Danko
content = `cat file`

Je pense que cette méthode est la plus "rare". C'est peut-être un peu délicat, mais cela fonctionne si cat est installé.

0
helloqiu

Une méthode encore plus efficace consiste à diffuser en continu en demandant au noyau du système d’exploitation d’ouvrir un fichier, puis de lire les octets bit par bit. Lors de la lecture d’un fichier par ligne dans Ruby, les données sont extraites du fichier 512 octets à la fois et sont ensuite divisées en «lignes».

En mettant en mémoire tampon le contenu du fichier, le nombre d’appels d’E/S est réduit lors de la division du fichier en blocs logiques.

Exemple:

Ajoutez cette classe à votre application en tant qu'objet de service:

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

Appelez-le et transmettez à la méthode :each un bloc:

filename = './somewhere/large-file-4gb.txt'
MyIO.new(filename).each{|x| puts x }

Lisez à ce sujet ici dans cet article détaillé:

Ruby Magic Slurping & Streaming Files Par AppSignal

0
Khalil Gharbaoui