2015-04-17 10 views
6

Ich versuche NIO FileSystem zu verwenden, um auf ein Glas in einem anderen Glas zuzugreifen. Rufen Sie die außerhalb jar my-outer.jar und die innere my-inner.jar (mit Java 8 und Windows 7, aber ich denke, dass ist nicht das Problem)Wie kann ich ein Dateisystem zu einem Glas in einem anderen Glas erstellen

Ich verwende den folgenden Code

String zipfilePath = "c:/testfs/my-outer.jar!/my-inner.jar"; 
    Path path = Paths.get(zipfilePath); 
    try(ZipFileSystem zipfs = (ZipFileSystem) FileSystems.newFileSystem(path, null)) 
    { ... } 

aber ich bin immer die unten Ausnahme, wenn diese newFileSystem zu erstellen versuchen:

Exception in thread "main" java.nio.file.FileSystemNotFoundException: C:\testfs\my-outer.jar!\my-inner.jar 

Beachten sie, dass, wenn ich nur das äußere Glas als Filesystem, das perfekt funktioniert gut und ich kann Dateien aus schön lesen und schreiben . Gerade wenn ich versuche, ins innere Archiv zu gelangen, beginnen die Schwierigkeiten.

Unterstützt FileSystem nicht die JarURLConnection-Notation?

+1

Vom Blick auf dekompilierte Quellen von ZipFileSystem scheint es, dass es nur "echte" Dateien unterstützt. Für verschachtelte ZIP (JAR) -Archive müssen Sie "low-level" java.util.zip-Paket verwenden (oder extrahieren Sie den inneren Kreisbogen auf den Datenträger, obwohl ich das nicht eine gute Lösung nennen würde). – vbezhenar

+0

Keine gute Idee. Selbst ein JAR-Dateisystem mit einer Ebene wird sehr schlecht funktionieren. – EJP

Antwort

3

Wie von vbezhenear und wie von mir selbst experimentiert die JarURLConnection Notation in der Form c:/testfs/my-outer.jar!/my-inner.jar scheint nicht durch die werkseigene Methode FileSystems.newFileSystem(Path path, ClassLoader loader) implementiert.

Sie können aber nach wie vor das innere Gefäß wie folgt zugreifen:

Path outerPath = Paths.get("c:/testfs/my-outer.jar"); 
try (FileSystem outerFS = FileSystems.newFileSystem(outerPath, null)) { 
    Path innerPath = outerFS.getPath("/my-inner.jar"); 
    try (FileSystem innerFS = FileSystems.newFileSystem(innerPath, null)) { 
     ... 
    } 
} 

--UPDATE--

Wenn Sie versuchen, eine URI anstelle eines Path verwenden Sie eine ZipFileSystem wie diese

erstellen
URI uri = URI.create("jar:file:/home/orto/stackoverflow/outer.jar!/inner.jar"); 
Map<String,String> env = Collections.emptyMap(); 
try(ZipFileSystem zipfs = (ZipFileSystem)FileSystems.newFileSystem(uri,env)) 
{...} 

Aber kein Glück Sie Zugang erhalten zu den outer.jar und nicht die inner.jar

Wenn Sie sich den Quellcode von JarFileSystemProvider betrachten, sehen Sie

@Override 
protected Path uriToPath(URI uri) { 
    String scheme = uri.getScheme(); 
    if ((scheme == null) || !scheme.equalsIgnoreCase(getScheme())) { 
     throw new IllegalArgumentException("URI scheme is not '" + getScheme() + "'"); 
    } 
    try { 
     String uristr = uri.toString(); 
     int end = uristr.indexOf("!/"); 
     uristr = uristr.substring(4, (end == -1) ? uristr.length() : end); 
     uri = new URI(uristr); 
     return Paths.get(new URI("file", uri.getHost(), uri.getPath(), null)) 
        .toAbsolutePath(); 
    } catch (URISyntaxException e) { 
     throw new AssertionError(e); //never thrown 
    } 
} 

Der Weg vor dem ersten "!" zerschneiden wird. Es gibt also keine Möglichkeit, direkt aus der Methode newFileSystem ein Dateisystem im internen Jar zu erstellen.

+0

Ich mag deine erste Antwort. Ich habe nicht verstanden, ob Ihr "Update" eine andere Antwort gibt oder nur meine Frage erklärt –

+2

Das "Update" ist nur da, um zu zeigen, dass es (noch) keine Implementierung der Funktion gibt, nach der Sie gesucht haben. (Erstellen eines ZipFileSystem mit JarURLConnection Notation) –

+0

Dies (nicht mehr wie bei 8u74) scheint als 'FileSystems.newFileSystem (innerPath, null) zu funktionieren' wirft 'ProviderNotFoundException' ab, weil' ZipFileSystemProvider.newFileSystem() 'ausbucht wenn' Pfad .getFileSystem()! = FileSystems.getDefault() '. – antak

Verwandte Themen