将Jar-URI转换为nio.Path

时间:2015-09-30 19:11:45

标签: java url path uri classloader

在一般情况下,我无法从URI转换为nio.Path。给定具有多个模式的URI,我希望创建一个nio.Path实例来反映此URI。

    //setup
    String jarEmbeddedFilePathString = "jar:file:/C:/Program%20Files%20(x86)/OurSoftware/OurJar_x86_1.0.68.220.jar!/com/our_company/javaFXViewCode.fxml";
    URI uri = URI.create(jarEmbeddedFilePathString);

    //act
    Path nioPath = Paths.get(uri);

    //assert --any of these are acceptable
    assertThat(nioPath).isEqualTo("C:/Program Files (x86)/OurSoftware/OurJar_x86_1.0.68.220.jar/com/our_company/javaFXViewCode.fxml");
    //--or assertThat(nioPath).isEqualTo("/com/our_company/javaFXViewCode.fxml");
    //--or assertThat(nioPath).isEqualTo("OurJar_x86_1.0.68.220.jar!/com/our_company/javaFXViewCode.fxml")
    //or pretty well any other interpretation of jar'd-uri-to-path any reasonable person would have.

此代码目前在FileSystemNotFoundException电话上引发Paths.get()

这种转换的实际原因是询问有关其包位置和文件名的事物的结果路径 - 换句话说,只要生成的路径对象保留...com/our_company/javaFXViewCode.fxml部分,那么它仍然是我们使用NIO Path对象非常方便。

这些信息大部分实际用于调试,所以我不可能改进我们的代码以避免在这个特定实例中使用Paths而是使用URI或简单的字符串,但这将涉及到对nio.Path对象已经方便提供的方法进行了一系列重组。

我已经开始深入研究the file system provider API并且遇到了比我想要处理这么小事情更复杂的问题。在URI指向非jar文件的情况下,是否有一种简单的方法可以将类加载器提供的URI转换为与OS可理解的遍历相对应的路径对象,而不是OS可理解但仍然有用在路径指向jar内的资源(或者zip或tarball)的情况下遍历?

感谢您的帮助

1 个答案:

答案 0 :(得分:2)

Java Path属于FileSystem。文件系统由FileSystemProvider实现。

Java附带两个文件系统提供程序:一个用于操作系统(例如WindowsFileSystemProvider),另一个用于zip文件(ZipFileSystemProvider)。这些是内部的,不应直接访问。

要获取Jar文件中的文件Path,您需要获取(创建)Jar文件内容的FileSystem。然后,您可以在该文件系统中获取Path文件。

首先,您需要解析Jar URL,最好使用JarURLConnection完成:

URL jarEntryURL = new URL("jar:file:/C:/Program%20Files%20(x86)/OurSoftware/OurJar_x86_1.0.68.220.jar!/com/our_company/javaFXViewCode.fxml");
JarURLConnection jarEntryConn = (JarURLConnection) jarEntryURL.openConnection();
URL jarFileURL = jarEntryConn.getJarFileURL(); // file:/C:/Program%20Files%20(x86)/OurSoftware/OurJar_x86_1.0.68.220.jar
String entryName = jarEntryConn.getEntryName(); // com/our_company/javaFXViewCode.fxml

完成后,您可以创建FileSystem并获取jar文件的Path。请记住,FileSystem是一个开源资源,完成后需要关闭:

try (FileSystem jarFileSystem = FileSystems.newFileSystem(jarPath, null)) {
    Path entryPath = jarFileSystem.getPath(entryName);
    System.out.println("entryPath: " + entryPath); // com/our_company/javaFXViewCode.fxml
    System.out.println("parent: " + entryPath.getParent()); // com/our_company
}