java - getclassloader - getresourceasstream path
Diferentes maneras de cargar un archivo como InputStream (6)
Cuál es la diferencia entre:
InputStream is = this.getClass().getClassLoader().getResourceAsStream(fileName)
y
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)
y
InputStream is = this.getClass().getResourceAsStream(fileName)
¿Cuándo son más apropiados para usar que los otros?
El archivo que quiero leer está en el classpath como mi clase que lee el archivo. Mi clase y el archivo están en el mismo jar y empaquetados en un archivo EAR, y se implementan en WebSphere 6.1.
Después de intentar algunas formas de cargar el archivo sin éxito, recordé que podía usar FileInputStream
, que funcionó perfectamente.
InputStream is = new FileInputStream("file.txt");
Esta es otra manera de leer un archivo en un InputStream
, lee el archivo de la carpeta actualmente en ejecución.
Funciona, prueba esto:
InputStream in_s1 = TopBrandData.class.getResourceAsStream("/assets/TopBrands.xml");
Hay diferencias sutiles en cuanto a cómo se interpreta el nombre de fileName
que está pasando. Básicamente, tienes 2 métodos diferentes: ClassLoader.getResourceAsStream()
y Class.getResourceAsStream()
. Estos dos métodos ubicarán el recurso de manera diferente.
En Class.getResourceAsStream(path)
, la ruta se interpreta como una ruta local al paquete de la clase desde la que se llama. Por ejemplo, String.getResourceAsStream("myfile.txt")
buscará un archivo en su ruta de clase en la siguiente ubicación: "java/lang/myfile.txt"
. Si su ruta comienza con una /
, entonces será considerada una ruta absoluta y comenzará a buscar desde la raíz de la ruta de clase. Así que llamar a String.getResourceAsStream("/myfile.txt")
buscará la siguiente ubicación en la ruta de tu clase.
ClassLoader.getResourceAsStream(path)
considerará que todas las rutas son rutas absolutas. Entonces, al llamar a String.getClassLoader().getResourceAsStream("myfile.txt")
y String.getClassLoader().getResourceAsStream("/myfile.txt")
ambos buscarán un archivo en su ruta de ./myfile.txt
en la siguiente ubicación: ./myfile.txt
Cada vez que menciono una ubicación en esta publicación, podría ser una ubicación en su propio sistema de archivos, o dentro del archivo jar correspondiente, dependiendo de la Clase y / o ClassLoader desde el que está cargando el recurso.
En su caso, está cargando la clase desde un Servidor de aplicaciones, por lo que debería usar Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)
lugar de this.getClass().getClassLoader().getResourceAsStream(fileName)
. this.getClass().getResourceAsStream()
también funcionará.
Lea este artículo para obtener información más detallada sobre ese problema en particular.
Advertencia para los usuarios de Tomcat 7 y anteriores.
Una de las respuestas a esta pregunta dice que mi explicación parece ser incorrecta para Tomcat 7. He intentado mirar alrededor para ver por qué ese sería el caso.
Así que he mirado el código fuente de WebAppClassLoader
de Tomcat para varias versiones de Tomcat. La implementación de findResource(String name)
(que es absolutamente responsable de producir la URL al recurso solicitado) es prácticamente idéntica en Tomcat 6 y Tomcat 7, pero es diferente en Tomcat 8.
En las versiones 6 y 7, la implementación no intenta normalizar el nombre del recurso. Esto significa que en estas versiones, classLoader.getResourceAsStream("/resource.txt")
puede no producir el mismo resultado que el classLoader.getResourceAsStream("resource.txt")
aunque debería (ya que eso lo especifica el Javadoc). [código fuente]
Sin embargo, en la versión 8, el nombre del recurso se normaliza para garantizar que la versión absoluta del nombre del recurso sea la que se utiliza. Por lo tanto, en Tomcat 8, las dos llamadas descritas anteriormente siempre deben devolver el mismo resultado. [código fuente]
Como resultado, debe tener mucho cuidado al usar ClassLoader.getResourceAsStream()
o Class.getResourceAsStream()
en versiones de Tomcat anteriores a 8. Y también debe tener en cuenta que class.getResourceAsStream("/resource.txt")
realidad llama a classLoader.getResourceAsStream("resource.txt")
(el encabezado /
se elimina).
Java antiguo simple en Java 7 normal simple y ninguna otra dependencia demuestra la diferencia ...
Puse file.txt
en c:/temp/
y puse c:/temp/
en el classpath.
Solo hay un caso donde hay una diferencia entre las dos llamadas.
class J {
public static void main(String[] a) {
// as "absolute"
// ok
System.err.println(J.class.getResourceAsStream("/file.txt") != null);
// pop
System.err.println(J.class.getClassLoader().getResourceAsStream("/file.txt") != null);
// as relative
// ok
System.err.println(J.class.getResourceAsStream("./file.txt") != null);
// ok
System.err.println(J.class.getClassLoader().getResourceAsStream("./file.txt") != null);
// no path
// ok
System.err.println(J.class.getResourceAsStream("file.txt") != null);
// ok
System.err.println(J.class.getClassLoader().getResourceAsStream("file.txt") != null);
}
}
Todas estas respuestas aquí, así como las respuestas en esta pregunta , sugieren que cargar URL absolutas, como "/foo/bar.properties" tratadas de la misma manera por class.getResourceAsStream(String)
y class.getClassLoader().getResourceAsStream(String)
. Este NO es el caso, al menos no en mi configuración / versión de Tomcat (actualmente 7.0.40).
MyClass.class.getResourceAsStream("/foo/bar.properties"); // works!
MyClass.class.getClassLoader().getResourceAsStream("/foo/bar.properties"); // does NOT work!
Lo siento, no tengo ninguna explicación satisfactoria, pero creo que Tomcat hace trucos sucios y su magia negra con los cargadores de clases y causa la diferencia. Siempre usé class.getResourceAsStream(String)
en el pasado y no he tenido ningún problema.
PD: También publiqué esto here
Use MyClass.class.getClassLoader().getResourceAsStream(path)
para cargar recursos asociados con su código. Use MyClass.class.getResourceAsStream(path)
como acceso directo, y para los recursos empaquetados dentro del paquete de su clase.
Use Thread.currentThread().getContextClassLoader().getResourceAsStream(path)
para obtener recursos que son parte del código del cliente, no muy limitados al código de llamada. Debe tener cuidado con esto, ya que el cargador de clases de contexto de subproceso podría estar apuntando a cualquier cosa.