【问题标题】:How do I get just the jar URL from a jar: URL containing a "!" and a specific file in the jar?如何从 jar 中获取 jar URL:包含“!”的 URL以及 jar 中的特定文件?
【发布时间】:2010-09-28 23:54:51
【问题描述】:

我在运行时得到一个 jar 文件 url:

jar:file:///C:/proj/parser/jar/parser.jar!/test.xml

如何将其转换为有效路径:

C:/proj/parser/jar/parser.jar.

我已经尝试过使用File(URI)getPath()getFile(),但没有成功。

【问题讨论】:

    标签: java file url path jar


    【解决方案1】:

    你可以这样做。这行得通

        ClassLoader loader = this.getClass().getClassLoader();
        URL url = loader.getResource("resource name");
        String[] filePath = null;
        String protocol = url.getProtocol();
        if(protocol.equals("jar")){
            url = new URL(url.getPath());
            protocol = url.getProtocol();
        }
        if(protocol.equals("file")){
            String[] pathArray = url.getPath().split("!");
            filePath = pathArray[0].split("/",2);
        }
        return filePath[1];
    

    【讨论】:

    • 不工作:后面的字符串部分!仍未删除
    【解决方案2】:
      //This code will work on both Windows and Linux
      public String path()
      {
      URL url1 = getClass().getResource("");
      String urs=url1.toString();
      urs=urs.substring(9);
      String truepath[]=urs.split("parser.jar!");
      truepath[0]=truepath[0]+"parser.jar";
      truepath[0]=truepath[0].replaceAll("%20"," ");
      return truepath[0];
      }
    

    【讨论】:

      【解决方案3】:

      我只需要这样做。

              URL url = clazz.getResource(clazz.getSimpleName() + ".class");
              String proto = url.getProtocol();
              boolean isJar = proto.equals("jar"); // see if it's in a jar file URL
      
              if(isJar)
              {
                  url = new URL(url.getPath()); // this nicely strips off the leading jar: 
                  proto = url.getProtocol();
              }
      
              if(proto.equals("file"))
              {
                   if(isJar) 
                      // you can truncate it at the last '!' here
              } 
              else if(proto == "http") {
                  ...
      

      【讨论】:

        【解决方案4】:

        此解决方案将处理路径中的空格。

        String url = "jar:file:/C:/dir%20with%20spaces/myjar.jar!/resource";
        String fileUrl = url.substring(4, url.indexOf('!'));
        File file = new File(new URL(fileUrl).toURI());
        String fileSystemPath = file.getPath();
        

        或以 URL 对象开头:

        ...
        String fileUrl = url.getPath().substring(0, url.indexOf('!'));
        ...
        

        【讨论】:

          【解决方案5】:

          有些人可能会认为这有点“hacky”,但它会在这种情况下完成这项工作,而且我相信它会比在其他建议中创建所有这些对象更好。

          String jarUrl = "jar:file:/C:/proj/parser/jar/parser.jar!/test.xml";
          
          jarUrl = jarUrl.substring(jarUrl.indexOf('/')+1, jarUrl.indexOf('!'));
          

          【讨论】:

          • 如果 URL 中有任何特殊(百分比编码)字符,这将失败。
          【解决方案6】:

          如果 MS-Windows 没有被前导斜杠冒犯,这可能会做到:

              final URL jarUrl =
                  new URL("jar:file:/C:/proj/parser/jar/parser.jar!/test.xml");
              final JarURLConnection connection =
                  (JarURLConnection) jarUrl.openConnection();
              final URL url = connection.getJarFileURL();
          
              System.out.println(url.getFile());
          

          【讨论】:

          • 我正在使用这个解决方案,尽管我希望有一种方法可以在不打开 jar(或直接解析,当然)的情况下做到这一点;似乎 URL 需要理解这个奇怪的东西!语法,否则需要存在理解它的子类。
          • (在 Java7 中) JarURLConnection 在执行上述代码时不会打开 JAR 文件。它只是代表您解析 URL。
          • @Marcono1234 如果 URI 指向 jar 中的某些内容,这将引发异常,因此带有感叹号,就像 OP 一样。
          • @DmitryAvtonomov,你是对的,我建议使用Paths.get 将不起作用。我删除了该评论。
          【解决方案7】:

          不确定是否有任何确切的方法可以满足您的需求,但这应该会让您接近:

          import static org.junit.Assert.assertEquals;
          
          import java.net.URL;
          
          import org.junit.Test;
          
          public class UrlTest {
          
              @Test
              public void testUrl() throws Exception {
                  URL jarUrl = new URL("jar:file:/C:/proj/parser/jar/parser.jar!/test.xml");
                  assertEquals("jar", jarUrl.getProtocol());
                  assertEquals("file:/C:/proj/parser/jar/parser.jar!/test.xml", jarUrl.getFile());
                  URL fileUrl = new URL(jarUrl.getFile());
                  assertEquals("file", fileUrl.getProtocol());
                  assertEquals("/C:/proj/parser/jar/parser.jar!/test.xml", fileUrl.getFile());
                  String[] parts = fileUrl.getFile().split("!");
                  assertEquals("/C:/proj/parser/jar/parser.jar", parts[0]);
              }
          }
          

          希望这会有所帮助。

          【讨论】:

          • 非常接近,但是 split() 的使用对我来说是太多的低级解析。 Sun 的 URL 实现似乎没有提供方法来处理 Sun 奇怪的 jar URL 的这种奇怪的 jarfile.jar!path/to/specific/file 语法;整个 shebang(双关语)由 getPath() 返回。但是正如 starblue 所提到的,JarURLConnection 似乎可以工作,尽管只能通过打开 jar。
          猜你喜欢
          • 2017-10-07
          • 1970-01-01
          • 2020-12-04
          • 1970-01-01
          • 1970-01-01
          • 2019-12-04
          • 1970-01-01
          • 2014-09-27
          • 2011-10-07
          相关资源
          最近更新 更多