Commons VFS因文件扩展名不同而失败



我是Commons VFS的新手,我试图了解如何打开一个嵌套的存档。我在源代码中找到了一个处理这个问题的例子。此测试通过。

@Test
void testTGZ() throws Exception {
    FileSystemManager fsManager = VFS.getManager();
        
    String uri = "tgz:file:///c:/data/nested.tgz!/test.tgz";
    FileObject archive = fsManager.resolveFile(uri);
    FileObject nestedFs = fsManager.createFileSystem(archive);
    // List the children of the archive file
    FileObject[] children = nestedFs.getChildren();
    for (FileObject child : children) {
        System.out.println(child.getURI());
    }
}

而这个用

就失败了
org.apache.commons.vfs2.FileSystemException: Could not find a file provider that can handle file "tgz:file:///C:/data/nested.tar.gz!/test.tar.gz".
@Test
void testTarGZ() throws Exception {
    FileSystemManager fsManager = VFS.getManager();
    String uri = "tgz:file:///c:/data/nested.tar.gz!/test.tar.gz";
    FileObject archive = fsManager.resolveFile(uri);
    FileObject nestedFs = fsManager.createFileSystem(archive);
    // List the children of the archive file
    FileObject[] children = nestedFs.getChildren();
    for (FileObject child : children) {
        System.out.println(child.getURI());
    }
}

除了名字,文件是相同的,所以为什么一个工作,而不是另一个?我做错了什么?

我遇到了同样的问题,经过调试,我能够找到问题的根源。

如果你看一下DefaultFileSystemManager类中的createFileSystem(FileObject file),你会发现它使用了FileTypeMap类中的getScheme(FileObject file)方法来检测方案:

/**
 * Find the scheme for the provider of a layered file system.
 * <p>
 * This will check the FileContentInfo or file extension.
 * </p>
 *
 * @return Scheme supporting the file type or null (if unknown).
 */
public String getScheme(final FileObject file) throws FileSystemException {
    // Check the file's mime type for a match
    final FileContent content = file.getContent();
    final String mimeType = content.getContentInfo().getContentType();
    if (mimeType != null) {
        return mimeTypeMap.get(mimeType);
    }
    // no specific mime-type - if it is a file also check the extension
    if (!file.isFile()) {
        return null; // VFS-490 folders don't use extensions for mime-type
    }
    final String extension = file.getName().getExtension();
    return extensionMap.get(extension);
}

当扩展名为tgz时,mimeType被求值为null,并且该方法尝试使用扩展名本身获取方案。在本例中,tgzextensionMap返回,DefaultFileSystemManager使用该值选择FileProvider(在本例中为TarFileProvider)。

当扩展名为tar.gz时,mimeType被解析为application/octet-stream, mimeTypeMap中没有任何映射,方法返回null。在此例中,DefaultFileSystemManager创建文件系统失败,因为没有找到FileProvider

解决方案:

可以在创建文件系统时指定FileProvider:

FileSystemManager manager = VFS.getManager();
// tgz file
String tgz = "file:/C:/data/nested.tgz";
FileObject tgzFileObject = manager.resolveFile(tgz);
FileObject tgzFileSystem = manager.createFileSystem("tgz", tgzFileObject);
// tar.gz file
String targz = "file:/C:/data/nested.tar.gz";
FileObject targzFileObject = manager.resolveFile(targz);
FileObject targzFileSystem = manager.createFileSystem("tgz", targzFileObject);

最新更新