为了列出类路径上特定目录的文件内容,我使用的是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))
{
...
由于dir对象具有以下值,因此可以:
jar:file:/C:/Users/pax/.../Detector-1.0.jar!/org/.../destinationdir
但是在其他环境中,目标目录直接存储在文件系统中。 dir对象包含值:
file:/C:/Users/pax/.../destinationdir
FileSystems.newFileSystem(...)
始终将/
和file:/C:/Users/pax/.../destinationdir
的异常作为URI抛出:
java.lang.IllegalArgumentException: Path component should be '/'
at sun.nio.fs.WindowsFileSystemProvider.checkUri(WindowsFileSystemProvider.java:68)
如何将FileSystem.newFileSystem
用于文件系统上的目标?
是否有更好的方法可以独立于特定类型的存储(文件系统或JAR文件)列出目录内容?
答案 0 :(得分:3)
以下问题的解决方案通过try-catch方法处理问题(&#34;目标在文件系统&#34;与#34;目标在JAR文件&#34;中):NIO2: how to generically map a URI to a Path? < / p>
此实用程序方法尝试获取正确的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);
}
}
包装器类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;
}
}
这使得FileSystem
实例的发布更加透明:
...
try (final PathReference fileObj = SignatureUtils.getPath(file))
{
...
try (InputStream fileStream = Files.newInputStream(fileObj.getPath()))
{
...