如何可靠地检测文件类型?

10

目标:给定文件,确定它是给定类型(XML、JSON、Properties等)中的哪一种。

考虑XML的情况- 在我们遇到这个问题之前,以下示例方法运行良好:

    try {
        saxReader.read(f);
    } catch (DocumentException e) {
        logger.warn("  - File is not XML: " + e.getMessage());
        return false;
    }
    return true;

当XML格式正确时,测试将会通过且方法返回true。但是,如果发生了什么不好的事情,无法解析文件,就会返回false。

然而,当我们处理格式不正确但仍为XML的文件时会出现问题。

我宁愿不依赖于.xml扩展名(总是失败),也不要查找文件内部的<?xml version="1.0" encoding="UTF-8"?>字符串等等。

是否有其他方法来处理这个问题?

在文件内部看到什么内容,可以“怀疑它可能是XML,虽然捕获了异常”。这是为了解析的目的。


有点相关:https://dev59.com/sHA65IYBdhLWcg3w2iep - PeterK
你无法得到一个明确的答案来回答“这是什么类型的文件?”,只能回答“我能假装它是X类型吗?”(答案可以是对于零个或多个X,而不仅仅是零个或一个)。但你可以加入统计数据,看看有多少<\w+>(可能是XML),多少"\w+"(可能是JSON)与总标记数相比,否则可能是属性。 - harold
3个回答


10

Apache Tika对我来说问题最少,而且不像Java 7那样平台特定:Files.probeContentType

import java.io.File;
import java.io.IOException;
import javax.activation.MimeType;
import org.apache.tika.Tika;

File inputFile = ...
String type = new Tika().detect(inputFile);
System.out.println(type);

对于 XML 文件,我得到了“application/xml”

对于属性文件,我得到了“text/plain”

然而,你可以添加一个探测器到新的 Tika() 中。

<dependency>
    <groupId>org.apache.tika</groupId>
    <artifactId>tika-core</artifactId>
    <version>1.xx</version>
</dependency>

2

对于那些不需要非常精确的检测(如rjdkolb提到的Java 7的Files.probeContentType方法)

Path filePath = Paths.get("/path/to/your/file.jpg");
String contentType = Files.probeContentType(filePath);

1
嗨,在win7 64位系统中,使用jdk1.8,上述方法对于所有文件类型都返回null。这是一个openjdk的bug吗,就像这些地方提到的一样-https://bugs.openjdk.java.net/browse/JDK-8080369 - bespectacled
这也会在某些MAC OS版本、Amazon Correto 8 Java等上出现问题。我不建议使用它。 - Miron Ophir
值得一提的是,默认实现可能只分析文件扩展名,如果扩展名不存在,则会失败。在OpenJDK 16中,这是在sun.nio.fs.AbstractFileTypeDetector中完成的。在我看来,这不能被视为可靠的文件类型检测。 - Eugene

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接