53 votes

File.open, open et IO.foreach en Ruby, quelle est la différence ?

Toutes les API suivantes font la même chose : ouvrir un fichier et appeler un bloc pour chaque ligne. Devrions-nous utiliser l'une plutôt que l'autre ?

File.open("file").each_line {|line| puts line}
open("file").each_line {|line| puts line}   
IO.foreach("file") {|line | puts line}

83voto

johannes Points 3878

Il existe des différences importantes entre ces trois choix.

File.open("file").each_line { |line| puts line }

  • File.open ouvre un fichier local et renvoie un objet fichier
  • le fichier reste ouvert jusqu'à ce que vous appeliez IO#close sur elle

open("file").each_line { |line| puts line }

Kernel.open regarde la chaîne pour décider ce qu'il faut en faire.

open(".irbrc").class # => File
open("http://google.com/").class # => StringIO
File.open("http://google.com/") # => Errno::ENOENT: No such file or directory - http://google.com/

Dans le second cas, le StringIO retourné par Kernel#open contient en fait le contenu de http://google.com/ . Si Kernel#open renvoie un File il reste ouvert jusqu'à ce que vous appeliez IO#close sur elle.

IO.foreach("file") { |line| puts line }

  • IO.foreach ouvre un fichier, appelle le bloc donné pour chaque ligne qu'il lit, et ferme le fichier ensuite.
  • Vous n'avez pas à vous soucier de fermer le fichier.

File.read("file").each { |line| puts line }

Vous n'avez pas mentionné ce choix, mais c'est celui que j'utiliserais dans la plupart des cas.

  • File.read lit complètement un fichier et le renvoie sous forme de chaîne.
  • Vous n'avez pas à vous soucier de fermer le fichier.
  • En comparaison avec IO.foreach cela indique clairement que vous avez affaire à un fichier.
  • La complexité de la mémoire pour cela est O(n). Si vous savez que vous avez affaire à un petit fichier, ce n'est pas un inconvénient. Mais s'il peut s'agir d'un gros fichier et que vous savez que votre complexité mémoire peut être inférieure à O(n), n'utilisez pas ce choix.

Il échoue dans cette situation :

 s= File.read("/dev/zero") # => never terminates
 s.each …

ri

ri est un outil qui vous montre la documentation ruby. Vous l'utilisez comme ceci sur votre shell.

ri File.open
ri open
ri IO.foreach
ri File#each_line

Avec cela, vous pouvez trouver presque tout ce que j'ai écrit ici et bien plus encore.

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