根据扩展名确定文件类型

时间:2021-02-23 16:00:58

标签: java file-extension

Java 中是否有一种简单的方法可以将文件扩展名转换为特定的文件类型?也就是说,我想将“.doc”翻译成“Microsoft Word 文档”。但我也不想查看每个文件来确定 mime 类型等,因为这会影响性能。

是否有列出所有当前接受的扩展名及其含义的库或数据库文件?我可以通过编程方式加载什么,然后在需要时进行搜索?

3 个答案:

答案 0 :(得分:0)

Microsoft has a support article 关于常见文件扩展名。

list of file formats”上的维基百科页面似乎非常详尽。

复制/粘贴其中一个(或两个)列表、使用文本编辑器调整格式并通过硬编码数组或外部资源文件将其推送到您的代码中应该很容易。

答案 1 :(得分:0)

请记住,如果您走这条路线,那么您就相信这些文件包含扩展程序声明的数据类型。这将是一个有点脆弱的解决方案,因为它只需要一个上游错误就可以破坏事情。

更好的 IMO 是从文件本身的前几个字节中读取 magic numbers(即文件签名)。几乎任何生产或商业软件都会这样做(绝​​对最低限度),而不是信任文件扩展名。恶意用户仍有可能伪造签名,但这需要有意识的操作,而不仅仅是编码错误。

这样做的成本与检查扩展的成本实际上没有本质区别;除非您正在处理大量文件或有一些非常紧迫的截止日期(在这种情况下,Java 可能不是最佳选择),这两种方法只需要要求操作系统从磁盘读取少量字节即可。检查幻数只需要读取更多字节,以及打开/关闭每个文件流的开销。

答案 2 :(得分:0)

据我所知,这些名称仅在注册表中可用。我已经看到尝试使用 Swing 的 FileView 来获取它们,但我不会依赖它,尤其是对于无头代码。

public static String getFullFileTypeName(String extension)
throws IOException,
       InterruptedException {

    if (!extension.startsWith(".")) {
        extension = "." + extension;
    }

    String progID = readDefaultValue(extension);
    String name = readDefaultValue(progID);

    return name;
}

private static String readDefaultValue(String node)
throws IOException,
       InterruptedException {

    String registryPath = "HKEY_CLASSES_ROOT\\" + node;
    ProcessBuilder builder = new ProcessBuilder(
        "reg.exe", "query", registryPath, "/ve");
    builder.redirectError(ProcessBuilder.Redirect.INHERIT);

    String value = null;
    Process process = builder.start();
    try (BufferedReader reader = new BufferedReader(
        new InputStreamReader(process.getInputStream()))) {

        String line;
        while ((line = reader.readLine()) != null) {
            int regSZIndex = line.indexOf("REG_SZ");
            if (regSZIndex >= 0) {
                value = line.substring(regSZIndex + 6).trim();
                break;
            }
        }

        // Consume remaining output.
        if (line != null) {
            int c;
            do {
                c = reader.read();
            } while (c >= 0);
            // As of Java 11, the above loop can be replaced with:
            //reader.transferTo(Writer.nullWriter());
        }
    }

    int returnCode = process.waitFor();
    if (returnCode != 0) {
        throw new IOException("Got return code " + returnCode
            + " from " + builder.command());
    }

    if (value == null) {
        throw new IOException(
            "Could not find value for \"" + registryPath + "\"");
    }

    return value;
}