Ruby’s File.open y la necesidad de f.close

Es de conocimiento común en la mayoría de los lenguajes de progtwigción que el flujo para trabajar con archivos es open-use-close. Sin embargo, vi muchas veces en los códigos ruby ​​llamadas File.open sin igual, y además encontré esta joya de conocimiento en los documentos ruby:

Las transmisiones de E / S se cierran automáticamente cuando son reclamadas por el recolector de basura.

darkredandyellow friendly irc toma el problema:
[17:12] sí, y también, el número de descriptores de archivos generalmente está limitado por el sistema operativo
[17:29] Supongo que puede agotar fácilmente las descripciones de archivos disponibles antes de que el recolector de basura lo limpie. en este caso, es posible que desee utilizar cerrarlos usted mismo. “reclamado por el recolector de basura”. significa que el GC actúa en algún momento en el futuro. y es caro muchas razones para cerrar archivos de manera explícita

  1. ¿Necesitamos cerrar explícitamente
  2. Si es así, ¿por qué el CG se cierra automáticamente?
  3. Si no, ¿por qué la opción?

Vi muchas veces en los códigos File.open llamadas File.open sin File.open

¿Puede dar un ejemplo? Solo lo veo en códigos escritos por principiantes que carecen del “conocimiento común en la mayoría de los lenguajes de progtwigción de que el flujo para trabajar con archivos es de uso abierto y cerrado”.

Los Rubyists experimentados cierran sus archivos explícitamente o, más idiomáticamente, usan la forma de bloque de File.open , que automáticamente cierra el archivo por usted. Su implementación básicamente se ve así:

 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 

Los guiones son un caso especial. Los scripts generalmente son tan cortos y utilizan tan pocos descriptores de archivos que simplemente no tiene sentido cerrarlos, ya que el sistema operativo los cerrará de todos modos cuando el script salga.

¿Necesitamos cerrar explícitamente?

Sí.

Si es así, ¿por qué el CG se cierra automáticamente?

Porque una vez que ha recostackdo el objeto, ya no hay forma de que cierre el archivo y, por lo tanto, se perderían los descriptores de archivo.

Tenga en cuenta que no es el recolector de basura el que cierra los archivos. El recolector de basura simplemente ejecuta los finalizadores de un objeto antes de que lo recopile. Sucede que la clase File define un finalizador que cierra el archivo.

Si no, ¿por qué la opción?

Porque la memoria desperdiciada es barata, pero los descriptores de archivos desperdiciados no lo son. Por lo tanto, no tiene sentido vincular el tiempo de vida de un descriptor de archivo a la duración de algún fragmento de memoria.

Simplemente no puede predecir cuándo se ejecutará el recolector de basura. Ni siquiera puede predecir si se ejecutará en absoluto : si nunca se queda sin memoria, el recolector de basura nunca se ejecutará, por lo tanto, el finalizador nunca se ejecutará, por lo tanto, el archivo nunca se cerrará.

Siempre debe cerrar descriptores de archivo después de su uso, que también lo vaciarán. A menudo las personas usan File.open o un método equivalente con bloques para manejar el tiempo de vida del descriptor de archivos. Por ejemplo:

 File.open('foo', 'w') do |f| f.write "bar" end 

En ese ejemplo, el archivo se cierra automáticamente.

  1. En caso de que no lo haga, o si hay alguna otra falla
  2. Ver 2.

De acuerdo con http://ruby-doc.org/core-2.1.4/File.html#method-c-open

Sin un bloque asociado, File.open es un sinónimo de :: new. Si se proporciona el bloque de código opcional, se pasará el archivo abierto como argumento y el objeto Archivo se cerrará automáticamente cuando finalice el bloque. El valor del bloque se devolverá desde File.open.

Por lo tanto, se cerrará automáticamente cuando el bloque finalice : D

Podemos usar la función File.read() para leer el archivo en ruby ​​….. como,

 file_variable = File.read("index.html") 

en este ejemplo, file_variable puede tener el valor completo de ese archivo ….