Jason Watkins
Tengo algunas preguntas sobre el uso del método close() cuando uso Java InputStreams. Por lo que veo y leo de la mayoría de los desarrolladores, siempre debe llamar explícitamente a close() en un InputStream cuando ya no sea necesario. Pero, hoy estuve investigando el uso de un archivo de propiedades de Java, y cada ejemplo que he encontrado tiene algo como esto:
Properties props = new Properties();
try {
props.load(new FileInputStream("message.properties"));
//omitted.
} catch (Exception ex) {}
Con el ejemplo anterior, no hay forma de llamar explícitamente a close() porque InputStream es inalcanzable después de que se usa. He visto muchos usos similares de InputStreams aunque parece contradecir lo que dice la mayoría de la gente 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 generalmente aceptable o si se prefiere hacer algo más como 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é forma es mejor y/o más eficiente? ¿O de verdad importa?
Jon
La clase de propiedades envuelve el flujo de entrada en un LineReader para leer el archivo de propiedades. Dado que 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 lo cierre por usted.
Una mejora que podrías hacer es usar IOUtils.closeQuietly()
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);
}
-
NO UTILIZAR, en desuso y eliminado sin reemplazo en IOUtils 2.6. “Utilice la declaración de prueba con recursos o maneje las excepciones suprimidas manualmente”.
– sergio
12 de febrero de 2018 a las 15:32
daniel voina
Iría con una prueba con recursos (al menos para Java 7+):
Properties props = new Properties();
try(InputStream fis = new FileInputStream("message.properties")) {
props.load(fis);
//omitted.
} catch (Exception ex) {
//omitted.
}
los close()
call debe llamarse automáticamente cuando se sale del bloque de prueba.
Los ejemplos en el Tutorial de propiedades cierra el FileInputStream
explícitamente después de la carga, por lo que creo que es seguro asumir que el load
El método no es responsable de ello, lo eres tú.
// create and load default properties
Properties defaultProps = new Properties();
FileInputStream in = new FileInputStream("defaultProperties");
defaultProps.load(in);
in.close();
Solo como referencia, revisé el armonía apache implementación de Propiedadesy lo hace no Cierra la transmisión al cargar.
-
el tutorial de Propiedades es la explicación que esperaba. Gracias por el enlace!
–Jason Watkins
21/10/2010 a las 20:52
kwo2002
Si está usando Java 7+, puede usar esto:
try(InputStream is = new FileInputStream("message.properties")) {
// ...
}
No menciona en la documentación que props.load
cerraría el flujo de entrada. Debe cerrar el flujo de entrada manualmente en un bloque finalmente 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 recolectados: si es posible, el que abre la transmisión debe cerrar la transmisión. De lo contrario, es muy fácil dejar una secuencia abierta (crees que una función la cerrará, pero no lo hace, o algo así…)
-
+1 a “el que abre la transmisión debe cerrar la transmisión” 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
21/10/2010 a las 20:36
-
La última versión del 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, hice TL;DR’d los documentos paraprops.load(Reader)
¡y no podía entender por qué mi flujo todavía estaba abierto!– Kevinarpe
7 oct 2013 a las 8:33
Parece que la primera muestra de código termina confiando en el método de finalización en FileInputStream para cerrar el archivo. Diría que su segundo ejemplo es mejor, aunque en ambos casos el archivo se cierra.
Hay casos como los flujos de bytes en los que cerrar no hace nada y se puede omitir; de lo contrario, creo que es mejor cerrar explícitamente el archivo en un bloque finalmente. Si lo abres, lo cierras.
Hay un libro en el sitio de Oracle llamado Rendimiento de la plataforma Java que analiza los finalizadores en su apéndice, dice:
Casi siempre es mejor hacer su propia limpieza en lugar de depender de un finalizador. El uso de un finalizador también puede dejar atrás recursos críticos que no se recuperarán durante un período de tiempo indeterminado. Si está considerando usar un finalizador para asegurarse de que los recursos importantes se liberen de manera oportuna, es posible que desee reconsiderarlo.
-
+1 a “el que abre la transmisión debe cerrar la transmisión” 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
21/10/2010 a las 20:36
-
La última versión del 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, hice TL;DR’d los documentos paraprops.load(Reader)
¡y no podía entender por qué mi flujo todavía estaba abierto!– Kevinarpe
7 oct 2013 a las 8:33
Unai Vivi
Permítanme agregar algo a las respuestas de otras personas.
Si puedes importar Apache Commons E/Spodría hacer uso de la siempre tan útil AutoCloseInputStream
s clases: envuelves tu InputStream
y luego simplemente usa su instancia envuelta y se cierra automáticamente tan pronto como se alcanza el final de la entrada o cuando la transmisión se cierra explícitamente, lo que ocurra primero.
Gracias a todos por las respuestas que proporcionaron. Desearía poder aceptarlas todas como LA respuesta. Esto ahora tiene sentido para mí.
–Jason Watkins
21/10/2010 a las 20:59