2015-04-17 6 views
6

Я пытаюсь использовать NIO FileSystem для доступа к банке внутри другой банки. Вызовите атмосферный Jar моего-outer.jar и внутреннюю мое-inner.jar (Использование Java 8 и Windows 7, но я думаю, что это не проблема)Как создать файловую систему в jar внутри другого jar

Я использую следующий код

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

, но я получаю исключение ниже при попытке создать что newFileSystem:

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

Обратите внимание, что, если я просто использовать внешний сосуд в качестве FileSystem, который работает прекрасно, и я могу читать и записывать файлы из него красиво , Это просто, когда я пытаюсь проникнуть во внутренний архив, что проблемы начинаются.

Не поддерживает ли файловая система обозначение JarURLConnection?

+1

От поиска к декомпилированным источникам ZipFileSystem кажется, что он поддерживает только «реальные» файлы. Для вложенных архивов ZIP (jar) вам нужно будет использовать пакет java.util.zip с низким уровнем (или извлечь внутреннюю дугу на диск, хотя я бы не назвал это хорошим решением). – vbezhenar

+0

Не очень хорошая идея. Даже одноуровневая файловая система JAR будет работать очень плохо. – EJP

ответ

3

Как уже было сказано в эксперименте, и, как я сам экспериментировал, обозначение JarURLConnection в форме c:/testfs/my-outer.jar!/my-inner.jar, по-видимому, не реализовано заводским методом FileSystems.newFileSystem(Path path, ClassLoader loader).

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

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--

Если вы пытаетесь использовать URI вместо Path вы можете создать ZipFileSystem как это

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)) 
{...} 

Но не повезло вы получите доступ к outer.jar и не inner.jar

Если вы посмотрите на исходный код JarFileSystemProvider вы видите

@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 
    } 
} 

Путь разрезают перед первым "!". Таким образом, нет способа напрямую создать файловую систему на внутренней панели из метода newFileSystem.

+0

Мне нравится ваш первый ответ. Я не понимал, что ваше «обновление» дало другой ответ или просто объясняло мой вопрос. –

+2

«Обновление» находится здесь, чтобы показать, что (пока) нет реализации функции, которую вы искали. (Создание ZipFileSystem, расположенного с нотной JarURLConnection) –

+0

Это, как представляется, работает как 'FileSystems.newFileSystem (innerPath, null)' throws 'ProviderNotFoundException', потому что' ZipFileSystemProvider.newFileSystem() 'выгружается, если' path .getFileSystem()! = FileSystems.getDefault() '. – antak

Смежные вопросы