tags:

views:

2287

answers:

5

Hi, I get a jar file url at runtime as:

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

How can this be converted to a valid path as:

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

I have already tried using File(URI), getPath(), getFile() in vain...

+2  A: 

Not sure of any exact method that will give you what you want, but this should get you close:

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

Hope this helps.

toolkit
Very close, but the usage of split() is too much low-level parsing for me. Sun's URL implementation doesn't seem to provide methods to deal with this weird jarfile.jar!path/to/specific/file syntax for Sun's weird jar URLs; the whole shebang (pun intended) is returned by getPath(). But JarURLConnection, as starblue mentioned, seems to work, although only through opening up the jar.
skiphoppy
A: 

Why don't you just parse the String and continue with your life?

Ubersoldat
Because it is generally better to use existing libraries.
starblue
Because I know diddly-squat about the format of this bizarre jar:file:// URL I am dealing with, which Sun invented and doesn't appear to have documented, and so therefore I can't possibly know if my parsing will work in all circumstances. At least if I use Sun's Java URL libraries, I have a slight chance that it'll work for more cases I might encounter. Maybe. If the libraries are good. They'll be more widely used and tested than anything I write, that's for sure.
skiphoppy
I voted you up because this is an important question, even though it is definitely a bad suggestion.
skiphoppy
There are other ways to raise important questions, aside from telling one to "continue with his life"
Leonel
+2  A: 

This might do it, if MS-Windows is not offended by a leading slash:

    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());
starblue
I am going with exactly this solution, although I wish there was a way to do this without opening the jar (or parsing directly, of course); seems like URL needs to understand this weird ! syntax, or else a subclass needs to exist which understands it.
skiphoppy
+1  A: 

Some might consider this to be a bit 'hacky', but it'll do the job in that instance and i'm sure it'd perform a damn sight better than creating all those objects in the other suggestions.

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

jarUrl = jarUrl.substring(jarUrl.indexOf('/')+1, jarUrl.indexOf('!'));
James Camfield
A: 

This solution will handle spaces in the path.

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();

or with a URL object to begin with:

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