Java 通过文件系统对象从文件系统读取

Java 通过文件系统对象从文件系统读取,java,jar,path,directory,filesystems,Java,Jar,Path,Directory,Filesystems,为了在类路径上列出特定目录的文件内容,我使用了Java7新的文件系统和路径特性。在一个部署中,目录直接存储在文件系统中。在另一个部署中,它存储在JAR文件中 我的方法可以很好地处理JAR文件:我创建一个文件系统对象,该对象引用JAR文件,并通过路径对象访问内容 ... URI dir = ... String[] array = dir.toString().split("!"); try (final FileSystem fs

为了在类路径上列出特定目录的文件内容,我使用了Java7新的
文件系统
路径
特性。在一个部署中,目录直接存储在文件系统中。在另一个部署中,它存储在JAR文件中

我的方法可以很好地处理JAR文件:我创建一个
文件系统
对象,该对象引用JAR文件,并通过
路径
对象访问内容

        ...
        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对象包含以下值:

file:/C:/Users/pax/.../destinationdir
FileSystems.newFileSystem(…)
始终为
/
文件:/C:/Users/pax/../destinationdir
作为URI引发以下异常:

java.lang.IllegalArgumentException: Path component should be '/'
at sun.nio.fs.WindowsFileSystemProvider.checkUri(WindowsFileSystemProvider.java:68)
如何将
FileSystem.newFileSystem
用于文件系统上的目标


是否有更好的方法可以独立于特定类型的存储(文件系统或JAR文件)列出目录内容?

以下问题的解决方案通过尝试捕获方法解决了这个问题(“文件系统上的目的地”与“JAR文件中的目的地”):

此实用程序方法尝试获取正确的
路径
实例。但可能会出现另一个问题:如果此目标资源包含在JAR文件(而不是文件系统)中,那么您只能通过其关联的
文件系统
实例访问该资源,该实例不能关闭!因此,您的helper方法需要返回
路径
对象以及
文件系统
实例(仅当它不直接在文件系统上时才需要)。调用程序必须手动关闭
文件系统
对象:

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);
    }
}
这使得
文件系统
实例的发布更加透明:

...
try (final PathReference fileObj = SignatureUtils.getPath(file))
{
    ...
    try (InputStream fileStream = Files.newInputStream(fileObj.getPath()))
    {
    ...

以下问题的解决方案通过try-catch方法解决了这个问题(“文件系统上的目标”与“JAR文件中的目标”):

此实用程序方法尝试获取正确的
路径
实例。但可能会出现另一个问题:如果此目标资源包含在JAR文件(而不是文件系统)中,那么您只能通过其关联的
文件系统
实例访问该资源,该实例不能关闭!因此,您的helper方法需要返回
路径
对象以及
文件系统
实例(仅当它不直接在文件系统上时才需要)。调用程序必须手动关闭
文件系统
对象:

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);
    }
}
这使得
文件系统
实例的发布更加透明:

...
try (final PathReference fileObj = SignatureUtils.getPath(file))
{
    ...
    try (InputStream fileStream = Files.newInputStream(fileObj.getPath()))
    {
    ...