2015-04-17 13 views
6

Tôi đang cố gắng sử dụng Hệ thống tệp NIO để truy cập vào một cái bình bên trong một cái bình khác. Gọi jar bên ngoài my-outer.jar và khu vực nội my-inner.jar (Sử dụng Java 8 và Windows 7 nhưng tôi nghĩ đó không phải là vấn đề)Làm thế nào tôi có thể tạo một Hệ thống tệp vào một cái bình bên trong một cái lọ khác

Tôi đang sử dụng đoạn mã sau

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

nhưng tôi nhận được ngoại lệ dưới đây khi cố gắng tạo mà newFileSystem:

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

Lưu ý rằng nếu tôi chỉ cần sử dụng jar bên ngoài như FileSystem, mà làm việc hoàn toàn tốt đẹp và tôi có thể đọc và ghi các file từ nó đẹp . Nó chỉ là khi tôi cố gắng tiếp cận với kho lưu trữ bên trong mà những rắc rối bắt đầu.

FileSystem không hỗ trợ ký hiệu JarURLConnection?

+1

Từ tìm đến các nguồn bị nén của ZipFileSystem, có vẻ như nó chỉ hỗ trợ các tệp "thực". Đối với kho lưu trữ lồng nhau ZIP (jar) bạn sẽ cần sử dụng gói java.util.zip "cấp thấp" (hoặc trích xuất vòng cung bên trong vào đĩa, mặc dù tôi sẽ không gọi đó là giải pháp tốt). – vbezhenar

+0

Không phải là một ý tưởng hay. Ngay cả một hệ thống tệp JAR một cấp sẽ hoạt động rất kém. – EJP

Trả lời

3

Như đã nói bởi vbezhenear và được thử nghiệm bởi bản thân ký hiệu JarURLConnection ở dạng c:/testfs/my-outer.jar!/my-inner.jar dường như không được thực hiện theo phương pháp nhà máy FileSystems.newFileSystem(Path path, ClassLoader loader).

Nhưng bạn vẫn có thể truy cập vào lọ bên trong như thế này:

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

Nếu bạn cố gắng sử dụng một URI thay vì một Path bạn có thể tạo một ZipFileSystem như

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

Nhưng không may mắn bạn có quyền truy cập vào outer.jar chứ không phải là inner.jar

Nếu bạn nhìn vào mã nguồn của JarFileSystemProvider bạn thấy

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

Con đường được cắt ra trước khi "!" đầu tiên. Vì vậy, không có cách nào để trực tiếp tạo ra một hệ thống tệp trên bình bên trong từ phương thức newFileSystem.

+0

Tôi thích câu trả lời đầu tiên của bạn. Tôi không hiểu nếu "cập nhật" của bạn đã đưa ra một câu trả lời khác hoặc chỉ giải thích câu hỏi của tôi –

+2

"Cập nhật" chỉ ở đó để cho thấy rằng (chưa) không triển khai tính năng bạn đang tìm kiếm. (Tạo một ZipFileSystem với ký hiệu JarURLConnection) –

+0

Điều này (không còn? Như ở 8u74) dường như hoạt động như 'FileSystems.newFileSystem (innerPath, null)' ném 'ProviderNotFoundException' vì' ZipFileSystemProvider.newFileSystem() 'bails out if' path .getFileSystem()! = FileSystems.getDefault() '. – antak

Các vấn đề liên quan