【问题标题】:How to construct a Path from a jar:file URL?如何从 jar:file URL 构造路径?
【发布时间】:2014-08-20 04:52:20
【问题描述】:

如何将Path 构造为jar:file URL?

调用Paths.get(new URI("jar:file:/C:/foo.jar!/bar.html")) 会抛出FileSystemNotFoundException(注意文件系统丢失,而不是文件本身)。

据我所知,这两个文件都存在。有什么想法吗?

【问题讨论】:

    标签: java jar uri


    【解决方案1】:

    Paths 尝试解析包含您的PathFileSystem。 (实际上这可能是一个实现细节。规范只是声明它将检查默认的FileSystem。)如果您还没有注册/创建这样的FileSystem,它将无法找到它。

    您将从 jar 文件创建一个新的FileSystem,并通过该FileSystem 访问条目Path

    Path path = Paths.get("C:/foo.jar");
    URI uri = new URI("jar", path.toUri().toString(),  null);
    
    Map<String, String> env = new HashMap<>();
    env.put("create", "true");
    
    FileSystem fileSystem = FileSystems.newFileSystem(uri, env);
    Path file = fileSystem.getPath("bar.html");
    System.out.println(file);
    

    然后你可以使用

    Paths.get(new URI("jar:file:/C:/foo.jar!/bar.html"))
    

    使用完FileSystem,注意正确关闭。

    有关 ZipFileSystemProvider 的更多信息,请参阅here

    【讨论】:

    • 这是一个非常狭窄的案例:如果 jarfile url 是内部引用:例如C:/foo.jar!src/file,您的方法将立即失败,并出现 URI not hierarchy 错误
    • @tribbloid 如果我理解正确,您是在举一个 jar 示例,该 jar 包含一个文件夹 (example-folder),其中包含一个文件 (bar.html),并试图访问该文件? Paths.get(new URI("jar:file:/C:/foo.jar!example-folder/bar.html")) 在这种情况下可以正常工作。请澄清。
    • @tribbloid 你能澄清一下吗?如果真的有问题,我想纠正这个问题。
    • 您确定Paths.get 方法有效吗?对我来说,如果指定了 jar 内的路径(即!/bar.html),则会引发FileSystemNotFoundException 异常,并且如果没有此路径,则会引发IllegalArgumentException
    • @Marcono1234 你为什么使用!/?考虑使用minimal reproducible example 提出新问题。
    【解决方案2】:

    从版本 7 开始,Java 允许我们拥有 FileSystems,不仅可以打开本地目录中的文件,还可以定义我们自己的文件系统。它有很多用途,例如拥有分布式文件系统、能够使用压缩、拥有 http 桥,等等……

    在您的情况下,您需要的是一种读取 jar 的方法。好吧,由于 jar 只是一个压缩文件,您可以使用默认的 FileSystem。没有比这更容易的了:

    import java.net.URI;
    import java.nio.file.FileSystem;
    import java.nio.file.FileSystems;
    import java.nio.file.Files;
    import java.util.HashMap;
    import java.util.Map;
    
    
    public class Main {
        public static void main(String [] args) throws Throwable {
            String jarName = "/Users/asantos/.m2/repository/ant/ant/1.6/ant-1.6.jar";
            String fileInside = "/META-INF/LICENSE.txt";
    
            Map<String, String> env = new HashMap<>(); 
    
            URI uri = URI.create("jar:file:"+jarName);
    
            try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) {
    
                System.out.println(new String(Files.readAllBytes(zipfs.getPath(fileInside))));
    
            } 
        }
    }
    

    我无耻地从文档中复制了我的代码,改用 jar 而不是 zip 文件:http://docs.oracle.com/javase/8/docs/technotes/guides/io/fsp/zipfilesystemprovider.html

    【讨论】:

    • 从 Java 7 开始可用,而不是 8
    • 我没有说只有 Java 8 有它。我只是陈述了我习惯的那个,但我会更新我的答案。谢谢。
    【解决方案3】:
    import java.net.URI;
    import java.nio.file.FileSystem;
    import java.nio.file.*;
    
    public static void method() {
        Map<String, String> env = new HashMap<>();
        // here false is used to indicate the zip file system provider not to create a new zip/jar file if it does not exist.
        env.put("create", Boolean.FALSE.toString());
        Path jarFilePath = Paths.get("C:\\test_jar_parent", "myjarfile.jar");
        String uriPath = "jar:" + jarFilePath.toUri().toString();
        URI uri = URI.create(uriPath);
        try (FileSystem jarFs = FileSystems.newFileSystem(uri, env, null)) {
            ...
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-22
      • 1970-01-01
      • 1970-01-01
      • 2012-11-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多