getResourceAsStream() frente a FileInputStream

Resuelto Vivin Paliath asked hace 14 años • 6 respuestas

Estaba intentando cargar un archivo en una aplicación web y recibía una FileNotFoundexcepción cuando usé FileInputStream. Sin embargo, usando la misma ruta, pude cargar el archivo cuando lo hice getResourceAsStream(). ¿Cuál es la diferencia entre los dos métodos y por qué uno funciona y el otro no?

Vivin Paliath avatar Feb 22 '10 07:02 Vivin Paliath
Aceptado

Los java.io.Fileconsortes y actúan sobre el sistema de archivos del disco local. La causa principal de su problema es que las rutas relativasjava.io dependen del directorio de trabajo actual. Es decir, el directorio desde el que se inicia la JVM (en su caso: la del servidor web). Esto puede ser, por ejemplo C:\Tomcat\bin, algo completamente diferente, pero no C:\Tomcat\webapps\contextname lo que usted esperaría que fuera. En un proyecto Eclipse normal, eso sería C:\Eclipse\workspace\projectname. Puede obtener información sobre el directorio de trabajo actual de la siguiente manera:

System.out.println(new File(".").getAbsolutePath());

Sin embargo, el directorio de trabajo no se puede controlar de ninguna manera mediante programación. Realmente debería preferir usar rutas absolutasFile en la API en lugar de rutas relativas. P.ej C:\full\path\to\file.ext.

No desea codificar ni adivinar la ruta absoluta en aplicaciones Java (web). Eso es sólo un problema de portabilidad (es decir, se ejecuta en el sistema X, pero no en el sistema Y). La práctica normal es colocar ese tipo de recursos en el classpath , o agregar su ruta completa al classpath (en un IDE como Eclipse, esa es la srccarpeta y la "ruta de compilación", respectivamente). De esta forma podrás agarrarlos con ayuda de ClassLoaderby ClassLoader#getResource()o ClassLoader#getResourceAsStream(). Es capaz de localizar archivos relativos a la "raíz" del classpath, como usted descubrió por coincidencia. En aplicaciones web (o cualquier otra aplicación que utilice múltiples cargadores de clases), se recomienda usar el ClassLoaderas devuelto por Thread.currentThread().getContextClassLoader()para poder mirar "fuera" del contexto de la aplicación web también.

Otra alternativa en las webapps es el ServletContext#getResource()y su homólogo ServletContext#getResourceAsStream(). Puede acceder a archivos ubicados en la webcarpeta pública del proyecto de la aplicación web, incluida la /WEB-INFcarpeta. Está ServletContextdisponible en servlets mediante el getServletContext()método heredado, puede llamarlo tal cual.

Ver también:

  • ¿Dónde colocar y cómo leer los archivos de recursos de configuración en una aplicación basada en servlet?
  • ¿Qué significa servletcontext.getRealPath("/") y cuándo debo usarlo?
  • Forma recomendada de guardar archivos cargados en una aplicación de servlet
  • Cómo guardar el archivo generado temporalmente en una aplicación web basada en servlet
BalusC avatar Feb 22 '2010 01:02 BalusC

getResourceAsStreames la forma correcta de hacerlo para aplicaciones web (como ya aprendió).

La razón es que la lectura del sistema de archivos no puede funcionar si empaqueta su aplicación web en un WAR. Esta es la forma correcta de empaquetar una aplicación web. De esa manera es portátil, porque no depende de una ruta de archivo absoluta o de la ubicación donde está instalado su servidor de aplicaciones.

duffymo avatar Feb 22 '2010 01:02 duffymo

La FileInputStreamclase trabaja directamente con el sistema de archivos subyacente. Si el archivo en cuestión no está físicamente presente allí, no podrá abrirlo. El getResourceAsStream()método funciona de manera diferente. Intenta localizar y cargar el recurso utilizando la ClassLoaderclase a la que se llama. Esto le permite encontrar, por ejemplo, recursos incrustados en jararchivos.

Dirk avatar Feb 22 '2010 00:02 Dirk

classname.getResourceAsStream() carga un archivo a través del cargador de clases de classname. Si la clase proviene de un archivo jar, desde allí se cargará el recurso.

FileInputStream se utiliza para leer un archivo del sistema de archivos.

Lachlan Roche avatar Feb 22 '2010 00:02 Lachlan Roche