Как получить только URL-адрес jar из jar: URL-адрес, содержащий ! а конкретный файл в банке?

Я получаю URL-адрес файла jar во время выполнения как:

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

Как это можно преобразовать в допустимый путь как:

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

Я уже пытался использовать File(URI), getPath(), getFile() тщетно.


person Community    schedule 31.12.2008    source источник


Ответы (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());
person starblue    schedule 31.12.2008
comment
Я использую именно это решение, хотя мне хотелось бы, чтобы был способ сделать это, не открывая банку (или, конечно, непосредственно анализируя); похоже, что URL должен понимать это странно! синтаксис, иначе должен существовать подкласс, который его понимает. - person skiphoppy; 15.07.2009
comment
(В Java7) JarURLConnection не открывает файл JAR при выполнении приведенного выше кода. Он просто анализирует URL-адрес от вашего имени. - person Gili; 04.11.2011
comment
@ Marcono1234 Marcono1234 Это вызовет исключение, если URI указывает на что-то внутри банки, таким образом, имея восклицательные знаки, как в случае с OP. - person Dmitry Avtonomov; 14.05.2019
comment
@DmitryAvtonomovov, вы правы, мое предложение использовать Paths.get не сработает. Я удалил этот комментарий. - person Marcono1234; 18.05.2019

Не уверен в каком-либо точном методе, который даст вам то, что вы хотите, но это должно приблизить вас:

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]);
    }
}

Надеюсь это поможет.

person toolkit    schedule 31.12.2008
comment
Очень близко, но использование split() для меня слишком низкоуровневый синтаксический анализ. Реализация URL-адресов Sun, похоже, не предоставляет методов для работы с этим странным синтаксисом jarfile.jar!path/to/specific/file для странных URL-адресов jar от Sun; весь шебанг (каламбур) возвращается getPath(). Но JarURLConnection, как упомянул starblue, похоже, работает, хотя и только через открытие банки. - person skiphoppy; 15.07.2009

Кто-то может счесть это немного "хакерским", но в этом случае он сделает свою работу, и я уверен, что он будет работать чертовски лучше, чем создание всех этих объектов в других предложениях.

String jarUrl = "jar:file:/C:/proj/parser/jar/parser.jar!/test.xml";

jarUrl = jarUrl.substring(jarUrl.indexOf('/')+1, jarUrl.indexOf('!'));
person James Camfield    schedule 31.12.2008
comment
Это с треском провалится, если в URL-адресе есть какие-либо специальные (закодированные в процентах) символы. - person cbley; 21.06.2016

Это решение будет обрабатывать пробелы в пути.

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('!'));
...
person dcstraw    schedule 21.05.2009

Я просто должен был сделать это.

        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") {
            ...
person peterk    schedule 08.02.2012

Вы можете сделать это. Это работает

    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];
person Hari Chandu Vakacharla    schedule 14.09.2015
comment
Не работает: часть строки после ! до сих пор не удален - person tribbloid; 04.09.2016