【问题标题】:Read from file system via FileSystem object通过 FileSystem 对象从文件系统中读取
【发布时间】:2014-07-22 22:35:49
【问题描述】:

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

我的方法适用于 JAR 文件:我创建了一个引用 JAR 文件的 FileSystem 对象并通过 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 文件)列出目录内容?

【问题讨论】:

    标签: java jar path directory filesystems


    【解决方案1】:

    以下问题的解决方法通过 try-catch 方法解决了问题(“文件系统上的目标”与“JAR 文件中的目标”):NIO2: how to generically map a URI to a Path?

    此实用程序方法尝试获取正确的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()))
        {
        ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多