¿Hay una API para obtener un recurso classpath (por ejemplo, de qué obtendría Class.getResource(String)
) como a java.nio.file.Path
? Idealmente, me gustaría usar las nuevas Path
API elegantes con recursos classpath.
143
¿Hay una API para obtener un recurso classpath (por ejemplo, de qué obtendría Class.getResource(String)
) como a java.nio.file.Path
? Idealmente, me gustaría usar las nuevas Path
API elegantes con recursos classpath.
Paths.get(URI)
, luego ´URL.toURI (), and last
getResource () `que devuelve aURL
. Es posible que pueda encadenarlos juntos. Aunque no lo he intentado.Respuestas:
Esta funciona para mí:
fuente
Thread.currentThread().getContextClassLoader().getResource(resourceName).toURI()
Adivinando que lo que quieres hacer es llamar a Files.lines (...) en un recurso que proviene del classpath, posiblemente desde un jar.
Dado que Oracle enreda la noción de cuándo una ruta es una ruta al no hacer que getResource devuelva una ruta utilizable si reside en un archivo jar, lo que debe hacer es algo como esto:
fuente
class.getResource
requiere una barra inclinada, perogetSystemResourceAsStream
no puedo encontrar el archivo cuando está prefijado con una barra inclinada.La solución más general es la siguiente:
El principal obstáculo es lidiar con las dos posibilidades, ya sea, tener un sistema de archivos existente que deberíamos usar, pero no cerrar (como con los
file
URI o el almacenamiento del módulo de Java 9), o tener que abrir y cerrar el sistema de archivos nosotros mismos (como archivos zip / jar).Por lo tanto, la solución anterior encapsula la acción real en un
interface
, maneja ambos casos, luego se cierra de forma segura en el segundo caso y funciona de Java 7 a Java 10. Prueba si ya hay un sistema de archivos abierto antes de abrir uno nuevo, por lo que también funciona en el caso de que otro componente de su aplicación ya haya abierto un sistema de archivos para el mismo archivo zip / jar.Se puede usar en todas las versiones de Java mencionadas anteriormente, por ejemplo, para enumerar el contenido de un paquete (
java.lang
en el ejemplo) comoPath
s, como este:Con Java 8 o más reciente, puede usar expresiones lambda o referencias de métodos para representar la acción real, p. Ej.
hacer lo mismo.
La versión final del sistema de módulos de Java 9 ha roto el ejemplo de código anterior. El JRE devuelve inconsistentemente la ruta
/java.base/java/lang/Object.class
porObject.class.getResource("Object.class")
donde debería ser/modules/java.base/java/lang/Object.class
. Esto se puede solucionar anteponiendo lo que falta/modules/
cuando la ruta principal se informa como inexistente:Luego, volverá a funcionar con todas las versiones y métodos de almacenamiento.
fuente
Resulta que puedes hacer esto, con la ayuda del proveedor del sistema de archivos Zip incorporado . Sin embargo, pasar un URI de recurso directamente a
Paths.get
no funcionará; en su lugar, primero debe crear un sistema de archivos zip para el URI jar sin el nombre de la entrada, luego consulte la entrada en ese sistema de archivos:Actualizar:
Se ha señalado correctamente que el código anterior contiene una fuga de recursos, ya que el código abre un nuevo objeto FileSystem pero nunca lo cierra. El mejor enfoque es pasar un objeto de trabajo similar al consumidor, al igual que la respuesta de Holger. Abra el Sistema de archivos ZipFS el tiempo suficiente para que el trabajador haga lo que tenga que hacer con la Ruta (siempre que el trabajador no intente almacenar el objeto Ruta para su uso posterior), luego cierre el Sistema de archivos.
fuente
newFileSystem
puede generar múltiples recursos abiertos para siempre. Aunque el anexo @raisercostin evita el error al intentar crear un sistema de archivos ya creado, si intenta utilizar el devueltoPath
obtendrá unClosedFileSystemException
. La respuesta de @Holger funciona bien para mí.FileSystem
. Si se carga un recurso de un tarro, y después crea la requeridaFileSystem
- elFileSystem
también le permitirá cargar otros recursos de la misma tarro. Además, una vez que haya creado el nuevoFileSystem
, puede intentar cargar el recurso nuevamente usandoPaths.get(Path)
y la implementación usará automáticamente el nuevoFileSystem
.#getPath(String)
método en elFileSystem
objeto.Escribí un pequeño método auxiliar para leer
Paths
los recursos de tu clase. Es bastante útil de usar, ya que solo necesita una referencia de la clase en la que ha almacenado sus recursos, así como el nombre del recurso en sí.fuente
No puede crear URI a partir de recursos dentro del archivo jar. Simplemente puede escribirlo en el archivo temporal y luego usarlo (java8):
fuente
Leer un archivo de la carpeta de recursos usando NIO, en java8
fuente
Debe definir el Sistema de archivos para leer el recurso del archivo jar como se menciona en https://docs.oracle.com/javase/8/docs/technotes/guides/io/fsp/zipfilesystemprovider.html . Tengo éxito al leer el recurso del archivo jar con los siguientes códigos:
fuente