leer - obtener la ruta de mi proyecto en java
Obteniendo FileSystemNotFoundException de ZipFileSystemProvider al crear una ruta a un recurso (4)
Tengo un proyecto de Maven y dentro de un método quiero crear una ruta para un directorio en mi carpeta de recursos. Esto se hace así:
try {
final URI uri = getClass().getResource("/my-folder").toURI();
Path myFolderPath = Paths.get(uri);
} catch (final URISyntaxException e) {
...
}
El URI
generado se ve como jar:file:/C:/path/to/my/project.jar!/my-folder
.
El stacktrace es el siguiente:
Exception in thread "pool-4-thread-1" java.nio.file.FileSystemNotFoundException
at com.sun.nio.zipfs.ZipFileSystemProvider.getFileSystem(ZipFileSystemProvider.java:171)
at com.sun.nio.zipfs.ZipFileSystemProvider.getPath(ZipFileSystemProvider.java:157)
at java.nio.file.Paths.get(Paths.java:143)
El URI
parece ser válido. La parte anterior !
apunta al archivo jar generado y la parte posterior a my-folder
en la raíz del archivo. He usado estas instrucciones antes para crear rutas a mis recursos. ¿Por qué estoy recibiendo una excepción ahora?
Además de @Uwe Allner y @mvreijn:
Ten cuidado con la URI
. A veces, el URI
tiene un formato incorrecto (por ejemplo, "file:/path/..."
y el correcto sería "file:///path/..."
) y no puede obtener un sistema de "file:///path/..."
adecuado.
En este caso, es toUri()
que el URI
se cree a partir del método toUri()
de la Path
.
En mi caso, modifiqué un poco el método initFileSystem
y utilicé en casos no excepcionales FileSystems.newFileSystem(uri, Collections.emptyMap())
. En casos excepcionales, se usa FileSystems.getDefault()
.
En mi caso, también fue necesario capturar la IllegalArgumentException
para manejar el caso con el Path component should be ''/''
. En Windows y Linux, la excepción se captura, pero FileSystems.getDefault()
funciona. En osx no ocurre ninguna excepción y se crea el newFileSystem
:
private FileSystem initFileSystem(URI uri) throws IOException {
try {
return FileSystems.newFileSystem(uri, Collections.emptyMap());
}catch(IllegalArgumentException e) {
return FileSystems.getDefault();
}
}
Ampliando la excelente respuesta de @Uwe Allner, un método a prueba de fallos para usar es
private FileSystem initFileSystem(URI uri) throws IOException
{
try
{
return FileSystems.getFileSystem(uri);
}
catch( FileSystemNotFoundException e )
{
Map<String, String> env = new HashMap<>();
env.put("create", "true");
return FileSystems.newFileSystem(uri, env);
}
}
Si lo llama con el URI que está a punto de cargar, se asegurará de que el sistema de archivos esté funcionando correctamente. Siempre llamo a FileSystem.close()
después de usarlo:
FileSystem zipfs = initFileSystem(fileURI);
filePath = Paths.get(fileURI);
// Do whatever you need and then close the filesystem
zipfs.close();
Debe crear el sistema de archivos antes de poder acceder a la ruta dentro del zip como
final URI uri = getClass().getResource("/my-folder").toURI();
Map<String, String> env = new HashMap<>();
env.put("create", "true");
FileSystem zipfs = FileSystems.newFileSystem(uri, env);
Path myFolderPath = Paths.get(uri);
Esto no se hace automáticamente.
Consulte http://docs.oracle.com/javase/7/docs/technotes/guides/io/fsp/zipfilesystemprovider.html
Si pretende leer el archivo de recursos, puede usar directamente getClass.getResourceAsStream
. Esto configurará el sistema de archivos implícitamente. La función devuelve un null
si no se pudo encontrar su recurso; de lo contrario, tendrá un flujo de entrada para analizar su recurso.