Hay diferencias sutiles en cuanto a cómo fileName
se interpreta lo que está pasando. Básicamente, tiene 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 lo está llamando. Por ejemplo vocación, String.getResourceAsStream("myfile.txt")
buscará un archivo en la ruta de clases en la siguiente dirección: "java/lang/myfile.txt"
. Si su ruta comienza con a /
, se considerará una ruta absoluta y comenzará a buscar desde la raíz de la ruta de clase. Por lo tanto, al llamar String.getResourceAsStream("/myfile.txt")
verá la siguiente ubicación en su ruta de clase ./myfile.txt
.
ClassLoader.getResourceAsStream(path)
considerará todas las rutas como rutas absolutas. Así que llamar String.getClassLoader().getResourceAsStream("myfile.txt")
y String.getClassLoader().getResourceAsStream("/myfile.txt")
lo hará tanto buscar un archivo en la ruta de clases en la siguiente direcció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 el Cargador de clases desde el que está cargando el recurso.
En su caso, está cargando la clase desde un Servidor de aplicaciones, por lo que debe usarla en 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 usuarios de Tomcat 7 y versiones inferiores
Una de las respuestas a esta pregunta dice que mi explicación parece ser incorrecta para Tomcat 7. He intentado mirar a mi alrededor para ver por qué ese sería el caso.
Así que he visto el código fuente de Tomcat WebAppClassLoader
para varias versiones de Tomcat. La implementación de findResource(String name)
(que es totalmente responsable de producir la URL del 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 que no produzca el mismo resultado que el classLoader.getResourceAsStream("resource.txt")
evento aunque debería (ya que eso es lo que 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 es 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")
realmente llama classLoader.getResourceAsStream("resource.txt")
( /
se despoja el inicio).
getClass().getResourceAsStream("/myfile.txt")
comporta de manera diferentegetClassLoader().getResourceAsStream("/myfile.txt")
.getClassLoader()
deString
, es un error o necesita una extensión?Úselo
MyClass.class.getClassLoader().getResourceAsStream(path)
para cargar recursos asociados con su código. ÚseloMyClass.class.getResourceAsStream(path)
como acceso directo y para recursos empaquetados dentro del paquete de su clase.Úselo
Thread.currentThread().getContextClassLoader().getResourceAsStream(path)
para obtener recursos que son parte del código del cliente, que no están estrechamente vinculados al código de llamada. Debe tener cuidado con esto, ya que el cargador de clases de contexto de subprocesos podría apuntar a cualquier cosa.fuente
Java simple en Java 7 simple y ninguna otra dependencia demuestra la diferencia ...
Pongo
file.txt
enc:\temp\
y pusec:\temp\
en la ruta de clase.Solo hay un caso en el que hay una diferencia entre las dos llamadas.
fuente
Todas estas respuestas por aquí, así como las respuestas en esta pregunta , sugieren que la carga de URL absolutas, como "/foo/bar.properties", se trata de la misma manera por
class.getResourceAsStream(String)
yclass.getClassLoader().getResourceAsStream(String)
. Este NO es el caso, al menos no en mi configuración / versión de Tomcat (actualmente 7.0.40).Lo siento, no tengo ninguna explicación satisfactoria, pero supongo que Tomcat hace trucos sucios y su magia negra con los cargadores de clases y causa la diferencia. Siempre lo usé
class.getResourceAsStream(String)
en el pasado y no he tenido ningún problema.PD: también publiqué esto aquí
fuente
ClassLoader.getResourceAsStream()
como absolutas? Esto es plausible porque, como se mencionó en algunos comentarios anteriores, enClass.getResourceAsStream
realidad llama a getClassLoader (). GetResourceAsStream` pero elimina cualquier barra diagonal inicial.Class.getResourceAsStream()
yClassLoader.getResourceAsStream()
finalmente terminan llamando,ClassLoader.findResource()
que es un método protegido cuya implementación predeterminada está vacía, pero cuyo javadoc declara explícitamente "Las implementaciones del cargador de clases deberían anular este método para especificar dónde para encontrar recursos ". Sospecho que la implementación de Tomcat de este método en particular puede ser defectuosa.WebAppClassLoader.findResource(String name)
en Tomcat 7 con la de Tomcat 8 , y parece que hay una diferencia clave. Tomcat 8 normaliza explícitamente el nombre del recurso agregando un encabezado/
si no contiene ninguno, lo que hace que todos los nombres sean absolutos. Tomcat 7 no. Eso es claramente un error en Tomcat 7Después de intentar algunas formas de cargar el archivo sin éxito, recordé que podía usarlo
FileInputStream
, lo que funcionó perfectamente.Esta es otra forma de leer un archivo en un archivo
InputStream
, lee el archivo de la carpeta actualmente en ejecución.fuente
Funciona, prueba esto:
fuente