Il est de notoriété publique dans la plupart des langages de programmation que le flux de travail avec les fichiers est open-use-close. Pourtant, j'ai vu plusieurs fois dans Ruby code des appels File.open inégalés, et en plus j'ai trouvé ce joyau de la connaissance dans le Ruby documents:
Les flux d'E/S sont automatiquement fermés lorsqu'ils sont réclamés par le garbage collector.
darkredandyellow irc amical prend le problème:
[17:12] oui, et aussi, le nombre de descripteurs de fichiers est généralement limité par le système d'exploitation
[17:29] Je suppose que vous pouvez facilement manquer de descripteurs de fichiers disponibles avant le garbage collector nettoie. dans ce cas, vous voudrez peut-être les utiliser vous-même. "réclamé par le garbage collector." signifie que le GC agit à un moment donné dans le futur. et c'est cher. de nombreuses raisons de fermer explicitement des fichiers.
J'ai vu plusieurs fois dans Ruby codes inégalés
File.open
appels
Pouvez-vous donner un exemple? Je vois seulement que dans le code écrit par des débutants qui manquent de la "connaissance commune dans la plupart des langages de programmation que le flux pour travailler avec des fichiers est open-use- proche".
Les rubyistes expérimentés ferment explicitement leurs fichiers ou, plus idiomatiquement, utilisent la forme de bloc de File.open
, qui ferme automatiquement le fichier pour vous. Son implémentation ressemble essentiellement à ceci:
def File.open(*args, &block)
return open_with_block(*args, &block) if block_given?
open_without_block(*args)
end
def File.open_without_block(*args)
# do whatever ...
end
def File.open_with_block(*args)
yield f = open_without_block(*args)
ensure
f.close
end
Les scripts sont un cas particulier. Les scripts sont généralement si courts et utilisent si peu de descripteurs de fichiers qu'il n'est tout simplement pas logique de les fermer, car le système d'exploitation les fermera de toute façon lorsque le script se fermera.
Faut-il fermer explicitement?
Oui.
Si oui, pourquoi le GC se ferme-t-il automatiquement?
Parce qu'après avoir collecté l'objet, il n'y a plus aucun moyen pour vous de fermer le fichier, et ainsi vous fuiriez les descripteurs de fichier.
Notez que ce n'est pas le garbage collector qui ferme les fichiers. Le garbage collector exécute simplement les finaliseurs d'un objet avant de le collecter. Il se trouve que la classe File
définit un finaliseur qui ferme le fichier.
Sinon, alors pourquoi l'option?
Parce que la mémoire gaspillée est bon marché, mais pas les descripteurs de fichiers gaspillés. Par conséquent, il n'est pas logique de lier la durée de vie d'un descripteur de fichier à la durée de vie d'un morceau de mémoire.
Vous ne pouvez tout simplement pas prédire quand le garbage collector fonctionnera. Vous ne pouvez même pas prédire si cela fonctionnera du tout : si vous ne manque de mémoire, le garbage collector ne fonctionnera jamais, donc le finaliseur ne fonctionnera jamais, donc le fichier ne sera jamais fermé.
Vous devez toujours fermer les descripteurs de fichiers après utilisation, cela les videra également. Souvent, les gens utilisent File.open ou une méthode équivalente avec des blocs pour gérer la durée de vie du descripteur de fichier. Par exemple:
File.open('foo', 'w') do |f|
f.write "bar"
end
Dans cet exemple, le fichier est fermé automatiquement.
Selon http://Ruby-doc.org/core-2.1.4/File.html#method-c-open
Sans bloc associé, File.open est synonyme de :: new. Si le bloc de code facultatif est donné, le fichier ouvert sera passé en argument et l'objet File sera automatiquement fermé à la fin du bloc. La valeur du bloc sera renvoyée par File.open.
Par conséquent, sera automatiquement fermé à la fin du bloc : D