如何使用绝对路径为*目录*创建FileSystem对象?

时间:2018-09-03 08:33:52

标签: java java-io java.nio.file

我正在创建一个命令行应用程序,根据给定的参数,该应用程序需要将一些文件(多个)输出到 ZIP文件普通文件夹

我的方法是用FileSystem封装目标(普通文件夹/ ZIP文件)。

我的问题是,除了当前工作目录表示绝对路径之外,我无法成功地为目录创建FileSystem对象我的硬盘上的strong>:

public class FileSystemWriteTest {
    public static void main(String[] args) throws IOException {
        Path absolutePath = Paths.get("target", "testpath").toAbsolutePath();
        System.out.println(String.format("user.dir before change:\n %s", System.getProperty("user.dir")));


        System.setProperty("user.dir", absolutePath.toString());
        System.out.println(String.format("changed user.dir:\n %s", System.getProperty("user.dir")));
        FileSystem defaultSystem = FileSystems.getDefault();
        Path testFilePath = defaultSystem.getPath("test.file");
        System.out.println(String.format("expected to be in changed user.dir:\n %s", testFilePath.toAbsolutePath()));


        URI uri = absolutePath.toUri();
        System.out.println(String.format("URI: %s", uri));
        FileSystem localFileSystem =
                FileSystems.newFileSystem(uri, Collections.emptyMap());
        Path file = localFileSystem.getPath("test.txt");
        System.out.println(file.toAbsolutePath());
    }
}

输出为:

user.dir before change:
 D:\data\scm-workspace\anderes\Test
changed user.dir:
 D:\data\scm-workspace\anderes\Test\target\testpath
expected to be in changed user.dir:
 D:\data\scm-workspace\anderes\Test\test.file
URI: file:///D:/data/scm-workspace/anderes/Test/target/testpath/
Exception in thread "main" java.lang.IllegalArgumentException: Path component should be '/'
    at sun.nio.fs.WindowsFileSystemProvider.checkUri(Unknown Source)
    at sun.nio.fs.WindowsFileSystemProvider.newFileSystem(Unknown Source)
    at java.nio.file.FileSystems.newFileSystem(Unknown Source)
    at java.nio.file.FileSystems.newFileSystem(Unknown Source)
    at com.oc.test.filesystem.FileSystemWriteTest.main(FileSystemWriteTest.java:27)

如果我更改为FileSystems.newFileSystem(Path, Classloader),则异常更改为:

Exception in thread "main" java.nio.file.ProviderNotFoundException: Provider not found
    at java.nio.file.FileSystems.newFileSystem(Unknown Source)
    at com.oc.test.filesystem.FileSystemWriteTest.main(FileSystemWriteTest.java:27)

看起来像这样仅适用于常规文件,不适用于目录

那么如何为 pwd 之外的目录创建FileSystem对象?

1 个答案:

答案 0 :(得分:1)

没有用于创建具有FileSystem之类的chroot语义的内置功能。默认文件系统仅支持file:///作为URI,并且不允许多个实例化。

在这方面,FileSystems.getDefault().getPath("test.file")会创建相对路径,就像Paths.get("test.file")一样。为默认文件系统和其他文件系统创建的相对路径之间的区别在于,在未指定其他基本路径的情况下(例如,在调用toAbsolutePath()或只是尝试打开它们时),解析行为是不同的。但是,针对当前工作目录进行解析不会使它们成为根路径。

实现文件系统不可知操作的最佳解决方案是让代码接收基础Path对象,以解决相对路径。

例如一个简单的树复制例程可能看起来像:

static void copyTree(Path sourceBase, Path targetBase) throws IOException {
    try {
        Files.walk(sourceBase).forEach(path -> {
            if(Files.isRegularFile(path)) try {
                Path target = targetBase.resolve(sourceBase.relativize(path).toString());
                if(!Files.isDirectory(target.getParent()))
                    Files.createDirectories(target.getParent());
                Files.copy(path, target, StandardCopyOption.COPY_ATTRIBUTES);
            } catch(IOException ex) {
                throw new UncheckedIOException(ex);
            }
        });
    } catch(UncheckedIOException ex) {
        throw ex.getCause();
    }
}

对于此方法,无论是从硬盘驱动器目录复制到另一个硬盘驱动器目录或zip文件系统,还是从zip文件系统复制到硬盘驱动器,还是从zip文件复制到另一个zip文件都没有关系,等

最有趣的部分是调用sourceBase.relativize(path),以获取从源基本路径到实际文件的子路径的相对路径。由于相对的Path实例仍然绑定到特定的文件系统,因此代码在将toString()传递给targetBase.resolve(…)之前会调用path.resolve(string),以确保它可以在不同的文件系统上工作。请注意,path.resolve(path.getFileSystem().getPath(string))等效于Path。如果该方法首先检查两个String实例是否属于同一个文件系统,则在这种情况下跳过FusionCharts.ready(function() { var revenueChart1 = new FusionCharts({ type: 'doughnut2d', renderAt: 'chart-container1', width: '100%', height: '350', dataFormat: 'json', dataSource: { "chart": { "caption": "Caption", "subCaption": "Sub-caption", "showValues": "0", "showLabels": "0", "showLegend": "1", "legendPosition": "RIGHT", "numberPrefix": "$", "startingAngle": "310", "showTooltip": "0", "decimals": "0" }, "data": [{ "label": "Work place services", "value": "28504" }] } }).render(); var revenueChart2 = new FusionCharts({ type: 'doughnut2d', renderAt: 'chart-container2', width: '100%', height: '350', dataFormat: 'json', dataSource: { "chart": { "caption": "Caption", "subCaption": "Sub-caption", "showValues": "0", "showLabels": "0", "showLegend": "1", "legendPosition": "RIGHT", "numberPrefix": "$", "startingAngle": "310", "showTooltip": "0", "decimals": "0" }, "data": [{ "label": "Work place services", "value": "28504" }] } }).render(); var revenueChart3 = new FusionCharts({ type: 'doughnut2d', renderAt: 'chart-container3', width: '100%', height: '350', dataFormat: 'json', dataSource: { "chart": { "caption": "Caption", "subCaption": "Sub-caption", "showValues": "0", "showLabels": "0", "showLegend": "1", "legendPosition": "RIGHT", "numberPrefix": "$", "startingAngle": "310", "showTooltip": "0", "decimals": "0" }, "data": [{ "label": "Work place services", "value": "28504" }] } }).render(); }); 绕行是合理的。