getResourceAsStream () vs FileInputStream

Estaba intentando cargar un archivo en una aplicación web, y estaba obteniendo una excepción FileNotFound cuando utilicé FileInputStream . Sin embargo, utilizando la misma ruta, pude cargar el archivo cuando obtuve getResourceAsStream() . ¿Cuál es la diferencia entre los dos métodos, y por qué uno funciona mientras que el otro no?

El archivo java.io.File consortes actúa en el sistema de archivos del disco local. La causa raíz de su problema es que las rutas relativas en java.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 o algo completamente diferente, pero no C:\Tomcat\webapps\contextname o lo que sea que esperas que sea. En un proyecto de Eclipse normal, eso sería C:\Eclipse\workspace\projectname . Puede aprender sobre el directorio de trabajo actual de la siguiente manera:

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

Sin embargo, el directorio de trabajo de ninguna manera es controlable programáticamente. En realidad, debería preferir utilizar rutas absolutas en File API en lugar de rutas relativas. Por ejemplo, C:\full\path\to\file.ext .

No desea codificar ni adivinar la ruta absoluta en aplicaciones Java (web). Eso es solo un problema de portabilidad (es decir, se ejecuta en el sistema X, pero no en el sistema Y). La práctica habitual es colocar ese tipo de recursos en el classpath o agregar su ruta completa al classpath (en un IDE como Eclipse que es la carpeta src y la “ruta de comstackción”, respectivamente). De esta forma, puede tomarlos con la ayuda del ClassLoader por ClassLoader#getResource() o ClassLoader#getResourceAsStream() . Es capaz de localizar archivos relativos a la “raíz” de la ruta de clases, como usted, por coincidencia, descubrió. En aplicaciones weba (o cualquier otra aplicación que use múltiples cargadores de clases) se recomienda utilizar el ClassLoader tal como lo devuelve Thread.currentThread().getContextClassLoader() para que pueda mirar “fuera” del contexto de la aplicación web también.

Otra alternativa en webapps es ServletContext#getResource() y su contraparte ServletContext#getResourceAsStream() . Puede acceder a los archivos ubicados en la carpeta web pública del proyecto de aplicación web, incluida la carpeta /WEB-INF . ServletContext está disponible en servlets mediante el getServletContext() heredado getServletContext() , puede llamarlo tal cual.

Ver también:

  • ¿Dónde colocar y cómo leer los archivos de recursos de configuración en la aplicación basada en servlet?
  • ¿Qué significa servletcontext.getRealPath (“/”) y cuándo debería usarlo?
  • Forma recomendada para guardar archivos cargados en una aplicación servlet
  • Cómo guardar el archivo generado temporalmente en una aplicación web basada en servlet

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

La razón es que leer desde el 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. Es portátil de esa manera, porque no depende de una ruta de archivo absoluta o la ubicación donde está instalado su servidor de aplicaciones.

FileInputStream cargará la ruta del archivo que pasa al constructor como relativa desde el directorio de trabajo del proceso de Java. Por lo general, en un contenedor web, esto es algo así como la carpeta bin .

getResourceAsStream() cargará una ruta de archivo relativa desde el classpath de su aplicación .

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

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

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