没有I / O的Java中的文件类型检测

时间:2015-01-27 18:34:10

标签: java java-8 file-type

Java JDK中有一个检测文件类型的内置方法:

Files.probeContentType(Paths.get("/temp/word.doc"));

javadoc说FileTypeDetector可以检查文件名,或者它可以检查文件中的几个字节,这意味着它必须实际上尝试从URL中提取文件。

这在我们的应用程序中是不可接受的;该文件的内容只能通过InputStream获得。

我试图逐步查看代码以查看JDK实际上在做什么,但它似乎转到FileTypeDetectors.defaultFileTypeDetector.probeContentType(path),它转到sun.nio.fs.AbstractFileTypeDetector,我无法进入该代码,因为没有来源附件。

如何使用JDK文件类型检测并强制它使用我提供的文件内容,而不是让它自行执行I / O?

3 个答案:

答案 0 :(得分:2)

Files.probeContentType()的文档解释了如何插入自己的FileTypeDetector实现,但是如果您按照文档进行操作,您会发现没有可靠的方法来确保您的实现是选择的一个(想法是不同的实现作为彼此的后备,而不是替代)。当然没有任何记录的方法可以阻止内置实现读取目标文件。

您肯定可以在网络上的各个位置找到内容类型的常用文件扩展名的地图,也可能在您自己的系统上找到; mime.types是此类文件的通用名称。如果您想在这样的映射文件中仅依赖 ,那么您可能需要使用自己的自定义工具,而不是Java标准库。

答案 1 :(得分:0)

如果您担心阅读InputStream的内容,可以将其包含在PushBackInputStream中以“未读”这些字节,以便下一个检测器实现可以读取它。

通常二进制文件的幻数是4个字节,所以只有new PushBackInputStream(in, 4)就足够了。

PushBackInputStream pushbackStream = new PushBackInputStream(in, 4);
byte[] magicNumber = new byte[4];
//for this example we will assume it reads whole array
//for production you will need to check all 4 bytes read etc
pushbackStream.read(magicNumber);

//now figure out content type basic on magic number
ContentType type = ...
//now pushback those 4 bytes so you can read the whole stream
pushbackStream.unread(magicNumber);

//now your downstream process can read the pushbackStream as a
//normal InputStream and gets those magic number bytes back
...

答案 2 :(得分:0)

JDK的Files.probeContentType()只是加载JDK安装中可用的FileTypeDetector,并要求它检测MIME类型。如果不存在那么它什么都不做。

Apache有一个名为Tika的库,它可以完全满足您的需求。它确定给定内容的MIME类型。它也可以插入JDK,使用Tika生成Files.probeContentType()函数。请查看本教程以获取快速代码 - http://wilddiary.com/detect-file-type-from-content/