PAX*_*PAX 2 java filesystems directory jar path
为了列出类路径上特定目录的文件内容,我使用了 Java 7 的新FileSystem
功能Path
。在一个部署中,该目录直接存储在文件系统上。在另一个部署中,它存储在 JAR 文件中。
我的方法适用于 JAR 文件:我创建一个FileSystem
引用 JAR 文件的对象并通过Path
对象访问内容。
...
URI dir = ...
String[] array = dir.toString().split("!");
try (final FileSystem fs = FileSystems.newFileSystem(URI.create(array[0]), new HashMap<String, Object>()))
{
final Path directory = fs.getPath(array[1]);
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(directory))
{
...
Run Code Online (Sandbox Code Playgroud)
由于 dir 对象具有以下值,因此它可以工作:
jar:file:/C:/Users/pax/.../Detector-1.0.jar!/org/.../destinationdir
Run Code Online (Sandbox Code Playgroud)
但在其他环境中,目标目录直接存储在文件系统上。dir 对象包含值:
file:/C:/Users/pax/.../destinationdir
Run Code Online (Sandbox Code Playgroud)
FileSystems.newFileSystem(...)
/
始终为file:/C:/Users/pax/.../destinationdir
URI抛出以下异常:
java.lang.IllegalArgumentException: Path component should be '/'
at sun.nio.fs.WindowsFileSystemProvider.checkUri(WindowsFileSystemProvider.java:68)
Run Code Online (Sandbox Code Playgroud)
如何使用FileSystem.newFileSystem
文件系统上的目的地?
是否有更好的方法来独立于其特定类型的存储(文件系统或 JAR 文件)列出目录内容?
以下问题的解决方案通过 try-catch 方法解决了该问题(“文件系统上的目标”与“JAR 文件中的目标”):NIO2:如何一般地将 URI 映射到路径?
此实用程序方法尝试获取正确的Path
实例。但可能会出现进一步的问题:如果此目标资源包含在 JAR 文件(而不是文件系统)中,那么您只能通过其关联的FileSystem
实例访问该资源,而该实例不得关闭!因此,您的辅助方法需要返回Path
对象和FileSystem
实例(仅当它不直接位于文件系统上时才需要)。调用者必须FileSystem
手动关闭对象:
public static PathReference getPath(final URI resPath) throws IOException
{
try
{
// first try getting a path via existing file systems
return new PathReference(Paths.get(resPath), null);
}
catch (final FileSystemNotFoundException e)
{
/*
* not directly on file system, so then it's somewhere else (e.g.:
* JAR)
*/
final Map<String, ?> env = Collections.emptyMap();
final FileSystem fs = FileSystems.newFileSystem(resPath, env);
return new PathReference(fs.provider().getPath(resPath), fs);
}
}
Run Code Online (Sandbox Code Playgroud)
包装类PathReference
应该实现AutoClosable
,以便它可以在try
块中使用:
public class PathReference implements AutoCloseable
{
...
@Override
public void close() throws Exception
{
if (this.fileSystem != null)
this.fileSystem.close();
}
public Path getPath()
{
return this.path;
}
public FileSystem getFileSystem()
{
return this.fileSystem;
}
}
Run Code Online (Sandbox Code Playgroud)
这使得实例的释放FileSystem
更加透明:
...
try (final PathReference fileObj = SignatureUtils.getPath(file))
{
...
try (InputStream fileStream = Files.newInputStream(fileObj.getPath()))
{
...
Run Code Online (Sandbox Code Playgroud)