Java 切断与另一个URI相关的URI

Java 切断与另一个URI相关的URI,java,uri,Java,Uri,我们有resolve,它将a/b+c/d转换为a/b/c/d 我们有relative,它将a/b+a/b/c/d转换为c/d 有没有办法将a/b/c/d+c/d转换为a/b 对于我的特殊问题(类路径),URI不能转换为java.nio.file.Paths,错误如下 java.nio.file.InvalidPathException: Illegal char <:> at index 3: jar:file:/D:/devel/somejar.jar!/foo/Bar.clas

我们有
resolve
,它将
a/b
+
c/d
转换为
a/b/c/d

我们有
relative
,它将
a/b
+
a/b/c/d
转换为
c/d

有没有办法将
a/b/c/d
+
c/d
转换为
a/b


对于我的特殊问题(类路径),URI不能转换为
java.nio.file.Path
s,错误如下

java.nio.file.InvalidPathException: Illegal char <:> at index 3: jar:file:/D:/devel/somejar.jar!/foo/Bar.class
java.nio.file.InvalidPathException:索引3:jar:file:/D:/devel/somejar.jar处的非法字符/foo/Bar.class

我想将一个条目的目录(例如给定的
Bar.class
)和
getClassLoader().getResource().toURI()
生成的
URI
解析为
jar:file:/D:/devel/somejar.jar/foo

您可以使用
java.nio.file.Path
但您必须使用自定义文件系统,因为这里的URI方案是
jar
而不是
文件
。显示了一个示例

URI uri = URI.create("jar:file:/D:/devel/somejar.jar!/foo/Bar.class");

String[] array = uri.toString().split("!");
String jarFile = array[0];
String entryPath = array[1];
try(FileSystem fs = FileSystems.newFileSystem(URI.create(jarFile), new HashMap<>())) {
    Path path = fs.getPath(entryPath);
    URI parentUri = path.getParent().toUri();
    ...
}
public static void main(final String[] args) throws Exception {
    // get URI of class
    String clazz = "String.class";

    URI resourceURI = String.class.getResource(clazz).toURI();
    System.out.println(resourceURI);
    System.out.println(resourceURI.toString().replaceAll("^(.+?)!?/?" + clazz + "$", "$1"));

    clazz = "/lang/String.class";
    System.out.println(resourceURI.toString().replaceAll("^(.+?)!?/?" + clazz + "$", "$1"));

    clazz = "java/lang/String.class";
    System.out.println(resourceURI.toString().replaceAll("^(.+?)!?/?" + clazz +  "$", "$1"));
}

我不确定你到底想要实现什么。您可以使用regex简单地删除路径的结束部分。我以String.class为例

URI uri = URI.create("jar:file:/D:/devel/somejar.jar!/foo/Bar.class");

String[] array = uri.toString().split("!");
String jarFile = array[0];
String entryPath = array[1];
try(FileSystem fs = FileSystems.newFileSystem(URI.create(jarFile), new HashMap<>())) {
    Path path = fs.getPath(entryPath);
    URI parentUri = path.getParent().toUri();
    ...
}
public static void main(final String[] args) throws Exception {
    // get URI of class
    String clazz = "String.class";

    URI resourceURI = String.class.getResource(clazz).toURI();
    System.out.println(resourceURI);
    System.out.println(resourceURI.toString().replaceAll("^(.+?)!?/?" + clazz + "$", "$1"));

    clazz = "/lang/String.class";
    System.out.println(resourceURI.toString().replaceAll("^(.+?)!?/?" + clazz + "$", "$1"));

    clazz = "java/lang/String.class";
    System.out.println(resourceURI.toString().replaceAll("^(.+?)!?/?" + clazz +  "$", "$1"));
}
如果要尝试将数据加载到路径中,则可以执行以下操作:

public static void main(final String[] args) throws Exception {
    // get URI of class
    String clazz = "String.class";

    URI resourceURI = String.class.getResource(clazz).toURI();
    System.out.println(resourceURI.getScheme());
    System.out.println(resourceURI.getRawSchemeSpecificPart());
    URI fileURI = new URI(resourceURI.getRawSchemeSpecificPart());
    System.out.println(fileURI.getScheme());
    System.out.println(fileURI.getRawSchemeSpecificPart());
    Path path = Paths.get(fileURI);
    System.out.println(path);
    System.out.println(path.getParent());
}
jar:file:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/jre/lib/rt.jar/java/net/URISyntaxException.class jar:file:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/jre/lib/rt.jar/java/net


toString就是诀窍

这种方法要求类加载器返回一个
jar:
路径。有没有办法使第一部分(
toString.split()
)更通用?类加载器可以返回哪些可能的URI类型?如果资源始终位于文件系统上,即类文件或Jar中,那么
java.nio.file.Path
java.io.file
应该足以获取父路径。我不太确定文件系统上是否所有内容都存在,但如果这样说,我认为就足够了。我还不会接受这个答案,因为更一般的问题还没有得到足够的回答(当
c
是一个完整的路径时,我会更清楚地说明这一点),我在线程“main”java.nio.file.InvalidPathException中得到
异常:索引3处的非法字符:jar:file:/D:/bin/java/jdk8u65/jre/lib/rt.jar/第4行的java/net/URISyntaxException.class
。啊!Windows vs Linux传奇继续:)