【问题标题】:Commons VFS fails for different file extensionCommons VFS 因不同的文件扩展名而失败
【发布时间】:2021-04-19 20:36:05
【问题描述】:

我是 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());
    }
}

除了名称之外,这些文件都相同,那么为什么一个可以工作而另一个不行呢?我做错了什么?

【问题讨论】:

  • 这两个文件是如何创建的?使用tar zcf foo.tgz inputfilenames 创建的文件与使用tar cf foo.tar inputfilenames; gzip foo.tar 创建的文件不同。会不会是 Commons VFS 只处理一个而不处理另一个?
  • @JimGarrison 你可能是对的。我必须检查一下。

标签: java apache-commons-vfs


【解决方案1】:

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

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

/**
 * 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);

【讨论】:

    猜你喜欢
    • 2016-04-17
    • 2012-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-30
    相关资源
    最近更新 更多