2010-10-21 10 views
56

Tengo algunas preguntas sobre el uso del método close() al usar Java InputStreams. Según lo que veo y leo de la mayoría de los desarrolladores, siempre debes llamar explícitamente a close() en un InputStream cuando ya no sea necesario. Pero, hoy en día que estaba buscando en el uso de un archivo de propiedades Java, y cada ejemplo que he encontrado tiene algo como esto:Cierre Java InputStreams

Properties props = new Properties(); 
try { 
    props.load(new FileInputStream("message.properties")); 
    //omitted. 
} catch (Exception ex) {} 

Con el ejemplo anterior, no hay manera de llamar explícitamente a close() porque el InputStream es inalcanzable después de que se utiliza. He visto muchos usos similares de InputStreams a pesar de que parece contradecir lo que la mayoría de la gente dice sobre el cierre explícito. Leí los JavaDocs de Oracle y no menciona si el método Properties.load() cierra el InputStream. Me pregunto si esto es aceptable en general o si se prefiere hacer algo más parecido a lo siguiente:

Properties props = new Properties(); 
InputStream fis = new FileInputStream("message.properties"); 
try { 
    props.load(fis); 
    //omitted. 
} catch (Exception ex) { 
    //omitted. 
} finally { 
    try { 
     fis.close(); 
    } catch (IOException ioex) { 
     //omitted. 
    } 
} 

¿Qué camino es mejor y/o más eficiente? ¿O de verdad importa?

+0

Gracias a todos por las respuestas que nos ha facilitado. Ojalá pudiera aceptarlos a todos como LA RESPUESTA. Esto ahora tiene sentido para mí. –

Respuesta

21

Los ejemplos de la Properties Tutorial cierran la FileInputStream explícitamente después de la carga, por lo que creo que es seguro asumir que el método load no es responsable de la misma, lo eres.

// create and load default properties 
Properties defaultProps = new Properties(); 
FileInputStream in = new FileInputStream("defaultProperties"); 
defaultProps.load(in); 
in.close(); 

Sólo como referencia, he comprobado la ejecución de Apache HarmonyProperties, y lo hace no cerrar la corriente de carga.

+0

el tutorial de Propiedades es la explicación que estaba esperando. Gracias por el enlace! –

7

Parece que la primera muestra de código termina confiando en el método de finalización en FileInputStream para cerrar realmente el archivo. Diría que su segundo ejemplo es mejor, aunque en ambos casos el archivo se cierra.

Existen casos como las secuencias de bytes donde cerrar no hace nada y se pueden omitir, de lo contrario, creo que es mejor cerrar el archivo explícitamente en un bloque finally. Si lo abres, lo cierras.

Hay un libro en el sitio de Oracle llamado Java Platform Performance que discute finalizadores en su apéndice, que dice:

Usted es casi siempre mejor que hace su propia limpieza en lugar de depender de un finalizador. El uso de un finalizador también puede dejar recursos críticos que no se recuperarán durante un tiempo indeterminado. Si está considerando utilizar un finalizador para garantizar que los recursos importantes se liberen de manera oportuna, es posible que desee reconsiderarlo.

12

No menciona en la documentación que props.load cerraría el flujo de entrada. Debe cerrar la secuencia de entrada manualmente en un bloque finally como sugiere.

No es normal que una función cierre un InputStream. Se aplica la misma convención que con la memoria en lenguajes no recogidos de basura: si es posible, el que abre la secuencia debe cerrar la secuencia. De lo contrario, es muy fácil dejar una secuencia abierta (cree que una función va a cerrarla, pero no, o algo así ...)

+0

+1 a "quien abre la secuencia debe cerrar la secuencia" Si eso no es posible, el comentario del método debe indicarle a la persona que llama que lo haga. El primer ejemplo de código es una mala práctica. – leonbloy

+0

El último lanzamiento de parche de Java 1.6 tiene este comentario para 'props.load (Reader)': * La secuencia especificada permanece abierta después de que este método regrese. * Antes de encontrar esta pregunta y respuesta, tenía TL; DR'd los documentos para ' props.load (Reader) 'y no podía entender por qué mi transmisión aún estaba abierta. – kevinarpe

42

La clase Propiedades ajusta la secuencia de entrada en un LineReader para leer las propiedades archivo. Como usted proporciona el flujo de entrada, es su responsabilidad cerrarlo.

El segundo ejemplo es una mejor manera de manejar la transmisión, por mucho, no confíe en que alguien más la cierre por usted.

Una mejora que podría hacer es utilizar IOUtils.closeQuietly()

http://commons.apache.org/io/api-1.2/org/apache/commons/io/IOUtils.html#closeQuietly(java.io.InputStream)

para cerrar el flujo, por ejemplo,:

Properties props = new Properties(); 
InputStream fis = new FileInputStream("message.properties"); 
try { 
    props.load(fis); 
    //omitted. 
} catch (Exception ex) { 
    //omitted. 
} finally { 
    IOUtils.closeQuietly(fis); 
} 
+10

+1 para el 'closeQuietly'. – uckelman

+0

NO USE, desaprobado y eliminado sin reemplazo en IOUtils 2.6. "Utilice la declaración try-with-resources o maneje las excepciones suprimidas manualmente". – Sergio

2

Déjenme agregar algo a las respuestas de otras personas.

Si puede importar Apache Commons IO, se puede hacer uso de los AutoCloseInputStream s clases siempre tan prácticos: usted envuelve su InputStream y luego sólo tiene que utilizar su instancia envuelta y se pone automáticamente cerrado tan pronto como el final de la entrada tiene se ha alcanzado o cuando la transmisión se cierra explícitamente, lo que ocurra primero.

19

Me gustaría ir con unos recursos try-con-(al menos para Java 7+):

Properties props = new Properties(); 

try(InputStream fis = new FileInputStream("message.properties")) { 
    props.load(fis); 
    //omitted. 
} catch (Exception ex) { 
    //omitted. 
} 

La estrecha() llamada debería ser llamado de forma automática cuando se sale del bloque try.

+0

+1: pregunta con fecha, pero información relevante para hits de google. – tilpner

9

Si está utilizando Java 7+ puede utilizar esto:

try(InputStream is = new FileInputStream("message.properties")) { 
    // ... 
}