17 votes

Ajouter une seule ligne au fichier avec Ruby

J'aimerais ajouter une seule ligne en haut d'un fichier avec Ruby, comme ceci :

# initial file contents
something
else

# file contents after prepending "hello" on its own line
hello
something
else

Le code suivant remplace simplement le contenu de l'ensemble du fichier :

f = File.new('myfile', 'w')
f.write "test string"

24voto

the Tin Man Points 69148

C'est une tâche assez courante :

original_file = './original_file'
new_file = original_file + '.new'

Mettez en place le test :

File.open(original_file, 'w') do |fo|
  %w[something else].each { |w| fo.puts w }
end

Voici le code actuel :

File.open(new_file, 'w') do |fo|
  fo.puts 'hello'
  File.foreach(original_file) do |li|
    fo.puts li
  end
end

Renommez l'ancien fichier en quelque chose de sûr :

File.rename(original_file, original_file + '.old')
File.rename(new_file, original_file)

Montrez que cela fonctionne :

puts `cat #{original_file}`
puts '---'
puts `cat #{original_file}.old`

Quelles sorties :

hello
something
else
---
something
else

Il ne faut pas essayer de charger complètement le fichier en mémoire. Cela fonctionnera jusqu'à ce que vous obteniez un fichier plus grand que votre allocation de RAM, et que la machine se mette à ramper, ou pire, se plante.

Au lieu de cela, lisez-le ligne par ligne. La lecture de lignes individuelles reste extrêmement rapide et est évolutive. Vous devez disposer d'un espace suffisant sur votre disque pour stocker le fichier original et le fichier temporaire.

6voto

MrDatabase Points 6914

En fait, cela semble fonctionner :

#!usr/bin/ruby

f = File.open("myfile", "r+")
lines = f.readlines
f.close

lines = ["something\n"] + lines

output = File.new("myfile", "w")
lines.each { |line| output.write line }
output.close

6voto

David Hernandez Points 233

J'ai trouvé quelque chose comme ça, c'est un peu plus descriptif et moins cryptique que les autres solutions que j'ai vues :

def file_prepend(file, str)
  new_contents = ""
  File.open(file, 'r') do |fd|
    contents = fd.read
    new_contents = str << contents
  end
  # Overwrite file but now with prepended string on it
  File.open(file, 'w') do |fd| 
    fd.write(new_contents)
  end
end

Et vous pouvez l'utiliser comme ça :

file_prepend("target_file.txt", "hello world!\n")

6voto

Steven Penny Points 18523

Comme certains l'ont dit, il ne faut probablement pas l'utiliser pour les gros fichiers, mais c'est un début simple.

rd = IO.read 'myfile'
IO.write 'myfile', "hello\n" + rd

3voto

sarnold Points 62720

Il n'existe aucun mécanisme permettant de faire facilement ce que vous voulez faire.

Au lieu de cela, vous devrez ouvrir le fichier, supprimer le fichier, ouvrir un nouveau fichier sous l'ancien nom pour l'écriture, écrire votre contenu, puis écrire le nouveau fichier à partir du contenu de l'ancien fichier. C'est assez alambiqué à première vue, mais c'est simple en code :

$ cat prepend.rb 
#!/usr/bin/ruby

File.open("passwd", "r") do |orig|
    File.unlink("passwd")
    File.open("passwd", "w") do |new|
        new.write "test string"
        new.write(orig.read())
    end
end

Notez que le mécanisme que j'ai utilisé ne prend pas la peine de vérifier les erreurs -- vous devriez probablement gérer les erreurs à chaque fois qu'il y en a une. File.open() et la File.unlink() et il suppose que le contenu entier du fichier tiendra dans la mémoire. Un petit exemple :

$ rm passwd
$ cp /etc/passwd .
$ ./prepend.rb 
$ head passwd
test stringroot:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
$ 

Si vous voulez gérer des fichiers qui ne tiennent pas entièrement dans la mémoire, vous devriez coder une boucle comme celle-ci (non testé - il vaut mieux considérer ce pseudo-code) :

while (data=orig.read(4096)) {
    new.write(data)
}

Comme alternative, vous pouvez écrire dans un fichier temporaire, et si le processus d'écriture réussit, entonces supprimer le fichier et renommer le fichier temporaire en place. Quelle que soit l'approche la plus logique pour vous.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X