tika in action第四章中文

本文档介绍了Tika在处理文档类型检测方面的应用,详细探讨了互联网媒体类型系统、媒体类型的分类,以及Tika如何利用媒体类型检测机制。Tika维护了一个内部的MIME类型数据库,提供API进行媒体类型检测。文件格式判断方法包括文件名、内容类型提示、魔数字节、字符编码和其他机制。Tika的类型检测器结合多种方法提供精确的文件类型估计。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

自我学习记录!

Charpter4文档类型检测

       我们来讨论下分类系统。分类学是科学的分类。分类被用作以识别和归类的概念来更好的理解和共享的词汇描述事物。例如,林奈分类法(the Linnaean taxonomy)是经典的系统命名所有的生物机体通过使用两部分的拉丁名,其同时识别属类以及种类。“Homo sapiens”表明现代的人类物种是前类人物种的一部分,随着消失的“Homo neanderthalensis”人一样。同样的分类法也在用来识别数字文件格式,叫做互联网媒体类型系统。

       分类法经常是与识别和检测特定的事物相联系的。例如,生物学分类是以物种的出现信息的描述,其表现特征或增长模式,DNA结构等方式来识别任意的动植物的物种。同样的机制也在检测数字文档格式中使用。

       在这一章节,我们将会深入文档格式的分类以及解析如何使用分类与其他的机制来确定文档的实际的类别。第一步是介绍互联网媒体类型系统和tika如何处理媒体类型。然后,查看tika中不同类型的检测机制。最后将会把这些放在一起,通过一个简单的示例程序来帮你感受使用tika的文档类型检测系统。

4.1互联网媒体类型

       正如你在1.1.1节记住的,在RFC2046中记录的互联网媒体类型系统是最好的标准作为识别文档类型。媒体类型(或者说是MIME类型,通常被叫做互联网多用途邮件扩充协议标准)在无论何时你浏览网页或读取邮件内部交流中起关键性的作用。总之,MIME类型在你的电脑与某个特殊文件交互的任何时候都给出正确的执行程序。例如,你曾经想过你的浏览器是如何知道什么时候它遇到的是一个短视频,应该加载相应的播放器播放而不是将其作为二进制或文本内容展示在你的浏览器中。

       大多数的浏览器(展示的Firefox的媒体类型对应的程序)明确的或暗示地必须理解文件内部的媒体类型并且知道如何去处理。不知道互联网上的媒体类型与其相关的程序,你的浏览器将会展示出绝大多数的是纯ASCII文本,这可一点儿也没趣。

       我们深入到互联网媒体类型的命名主题。在这之后将会介绍8个顶级的媒体类型,就在IANA媒体类型注册中。我们将会简短的描述IANA注册与别的一些东西,以及tika如何对媒体类型注册中的信息使用来准确且可靠地检测媒体类型。

4.1.1媒体类型名的使用

       媒体类型名由type/subtype组成定义和一个可选的参数“name=value”,下图可见其基于林奈分类法。Type/subtype部分和参数名被限制为US-ASCII字符集,也以不区分大小写处理。

       Type/subtype部分告诉你正在处理的文档格式,可选的参数增加需要的特定格式信息去处理文档。例如,媒体类型“text/plain;charset=UTF-8”表明使用UTF-8编码的纯文本文档。同样的是,“image/jpeg”类型表明一个以JPEG/JFIF图像格式存储的图片。

             

当处理大量文档和媒体类型时,肯定会不时地遇到异常情况。常见的错误是媒体类型名部分的顺序反转,如“charset=utf-8;text/html”。一个工具如tika帮助程序免去处理这类问题的复杂性。

 

       现在我们知道一个媒体类型长什么样了,很自然地去想什么类型被使用,如何管理已知的媒体类型集。

4.1.2媒体类型的种类

       当前有8种正式的顶级媒体类型,就如下图所示的,以及成千上万中注册或已知的子类型。与林奈动物分类法相似,这些顶级媒体类型作为分类和管理互联网媒体类型分类的基础。

除了正式的8个顶级类型,有作为示例使用的保留类别“example/*”。一些实验性的程序可能会使用未注册的顶级类型格式“x-*/*”,但是更常见的使用未注册的子类型,像“application/x-*”或“image/x-*”。

随着媒体类型的确定,它们需要以某种方式持久化,这样别人就可以查找它们的定义并了解它们的关系。媒体类型为此存储在一个“media type registry”。在你试图创建自己的类型之前是有一些不变已存在的媒体类型是值得理解其中一些,包括最大的最易理解的源,IANA注册。

4.1.3IANA与其他类型注册

       在它其余职责中,IANA保留维持一份正式的注册媒体类型列表。这个列表是公开地在“http://www.iana.org/assignments/media-types/”网页上,任何人想要注册新的类型都需要按照RFC4288与4289描述的流程。

       有成百上千的正式注册类型,更多的正不断地添加。除了是最大的维持最好的媒体类型注册,IANA注册是重要的,因为其定义的媒体类型质量很高,不管是直接的类型与子类型关系,也是因为每个类型都捕获了经过评议的性质(魔数字节,文件扩展字等)。IANA是一个受人尊重的互联网标准但却在内部有对客户有许多有用的信息,有着很多的数据管理者确保捕获信息的准确性。

       也有很多未被正式注册的类型或社区广泛地检查就被广泛地使用。关于这类类型的信息很多时候是很难找出的,这需要搜索线上和线下的资源和检查误导的甚至是错误的信息。一些网页如“http://filext.com,http://file-extension.net/”等维持了大量的经常提供未知文件媒体类型最好的提示或一些信息的文件格式数据库。不幸的是,这些信息通常都是不完整的或矛盾的,但可喜的是tika通过大量其他的方式解决了一些问题,例如从多个已存在媒体类型注册组合信息,允许以常用的XML格式来编辑和管理,最后采取一个易理解的种类来代表媒体类型,考虑其比较,扩展字,管理。

4.2tika中的媒体类型

       媒体类型是文件与计算机交互的基本,它告诉你的计算机文件与什么程序相关联。准确而可靠地检测媒体类型是最重要的,这也是tika正好在做的。

       现在你知道了一些关于处理媒体类型的困难,如八个顶级类型与无数的子类型,如何去命名媒体类型和对其分类,在哪儿存储(在注册中,一些质量高,另一些则不),现在是时候告诉你tika如何简化处理媒体类型的复杂性的了。

       首先,tika在程序内部维护一个丰富的,易于升级的,易理解的MIME数据库,减少了外部存在的注册依赖。然后,tika提供Java API与分类对tika内部MIME数据库交互支持,使管理数据库的API和所有的分类检测媒体类型的方法(魔数字节,文件扩展字等)暴露。

媒体类型检测的方法完全地由tika内部的MIME数据库驱动。

             

              在深入到源码例子和在这章节MIME-info数据库之前,提醒你刷新你在2.1节中的使用tika源码的记忆。

      

       Tika项目维持着自己的媒体类型注册,其同时包含了正式的IANA注册的类型和实际中正在使用的已知类型。Tika注册保持着追溯相关的信息,如类型关系和识别媒体类型的文件格式关键字。这一节学习注册的基础和能使用访问引入类型信息的关键类。

4.2.1共享的MIME-info数据库

       Unix环境传统上没有标准的方式在程序之间共享文档类型信息的方式。这是对于常用的开源桌面环境(linux内核的Gnome和KDE等)的一个问题。这些环境力求用户体验与所有文档类型的标准图标和程序关联更加一致,类似于其商业对应(Windows或者mac桌面环境)。为了以独立平台的方式管理这些文档类型信息,提出了共享的MIME-inf数据库,以XML文件格式保存媒体类型信息。这个文件格式就是下面展示的,为tika所用的。

一个mime-info文件包含了一系列记录了描述单个媒体类型的mime-type。一个类型记录表明正式的类型名字和已知的别名。例如,许多正式注册的媒体类型也以早于正式的类型注册的实验性的“x-*”出名。一个类型记录可以包含人们交流中常用的类型名信息。就像大多数人愿意叫家里养的猫为 “a cat”而不是“member of the feliscatus种”,就像pdf文档比准确的application/pdf在常用的语言交流中更被偏好使用一样。

捕获mime-info文件中的媒体类型(tika-mimetypes.xml源码中)提供单一访问管理tika的媒体类型方式。Tika的丰富相当准确的mime-info文件并没有阻止你增加或删除某一项来迎合你的需求。只要确保你加入表4.1中的信息,它将帮助tika检测正确的文件类型,你的程序和操作系统将会找到正确的程序处理。

       在进一步的深入在mime-info数据库中的所有详细类型的信息,首先让我们找找使用tika的API如何去访问记录的类型信息。

4.2.2MediaType类

       Tika使用MediaType类来代表媒体类型。这个类的实例是不可改变的,仅包含媒体类型的“type/subtype”对和可选的参数“name=value”。类型和参数名正常是小写的,MediaType类支持标准的java对象相等与顺序对比方法来应对各种各样的数据结构。类在下图中以UML图结构的形式描绘。

       静态的MediaType.parse(string)方法用来返回媒体类型字符串(如:“text/plain;charset=utf-8”)给MediaType实例。这个类型的解析器是灵活的并且试图返回一个有效的媒体类型甚至给“畸形的输入”,但是如果传入的字符串不能代表一种媒体类型将会返回“null”。

       下面的例子展示了怎么去使用MediaType类中的关键方法。这个类所有的信息可以tika官网的API文档中全部找到:

       无效的MediaType实例不会做太多的事情,但是它们形成了高一层“MediaTypeRegistry”的概念,就是下节遇到的类。

4.2.3MediaTypeRegistry类

       Mime-info的XML数据库文件和其他的源文件中的类型信息可以通过这个类访问。正如类名所暗示的,这个类的实例是媒体类型及相关信息的注册。这个类和其重要的特点在figure4.5中描绘。

       Tika包含一个扩展性相对不错的媒体类型数据库文件,可以通过静态方法MediaTypeRegistry.getDefaultRegistry()访问。下面的例子是使用这一方法打印所有的媒体类型和类型别名。这超过了一千种类型!

       现在我们已经学习了媒体类型的注册,将会展现由其媒体类型信息驱动的tika媒体类型检测机制的灵活性和强大。所以,换句话说,tika媒体类型注册是更准确的,更容易访问的,更容易升级的和更充实的;这是更利于你的程序和软件利用,从而更好地去处理你所遇到的文件。

       一个媒体类型注册丰富的关键部分是媒体类型层次结构的概念。类型层次告诉你的程序媒体类型application/xml是文本类型text/plain的子类型,可以通过文本编辑器查看,而不是别的类型对应的程序。

4.2.4类型层次

       很多媒体类型是基于一个更通用的文件格式。例如,所有text/*类型像text/html应该被作为纯文本对待,就像使用查看在大多数网页浏览器中查看源特点一样。因此这是准确地去说text/html是常用的text/plain类型的特别例子。

       这些各种各样的类型层次(父与子类型关系,或特例)是不同于标准的互联网媒体类型系统的type/subtype分类的。即使说text/plain可以被看作text/*的超文本类型,在image/*中也没有相似的格式。事实上,“SVG,image/svg+xml”格式是基于xml,因此SVG图片也可以被当做XML文件处理,这个在figure4.6可以证明。这样的类型关系是常通过名字前缀暗示的(+xml)。例如,“Epub,application/epub+zip”格式常许多电子书通过一些预定义的内容作为zip(application/zip)结构。

       Tika有关于处理文本类型和名字前缀的内置的内容,就如+xml与+zip。Tika也知道基本上所有的文件都可以被当作application/octet-stream字节流。但是更明确的类型层次信息需要使用子类型元素在类型数据库中。

       这个种类的类型层次信息常用于试图决定一个特殊的文件怎样处理的情况。例如,即使你没有要求的工具处理Keynote,你也可以能够通过keynote zip结构的内容抽取一些有用的信息。

       Tika支持这样的使用情况是通过使类型层次信息通过MediaTypeRegistry类的getSuperType()和isSpecializationOf()方法更易获取。前面java的API方法返回最接近给定的媒体类型的supertype(或者null,给定的类型恰好是application/octet-stream),后者的方法检查是否给定的类型是另一个常用类型的特例。GetSuperType()方法的使用:

       这是关于媒体类型自身的所有了。现在转到找出如何你能够得出给定文件的媒体类型,通过使用关于如何捕获和代表的信息。有了大量的媒体类型信息的知识后,检测给定文件的媒体类型也比你希望的复杂。Tika简化了这个一过程,我们将会给你展示如何做到的。

4.3文件格式判断

       生物学家使用像叶子的形状的信息来区分不同物种的树,羽毛的颜色和形式来判断鸟的物种。同样地,文件格式的研究者可以使用数字文件的字符特点来检测这些文件的类型。这一节将会是个给这样的人的引导,提供给你一个全范围的工具来检测不平常的文件。

       我们将会以文件名模式,一个使用最广和最简单的检测媒体类型的方法。将学习内容类型提示,魔数字节,字符编码,一系列的易于理解的由tika提供的数字特点来识别文件类型。章节后面部分包含高级的特点例如XML结构或组合文件名与数字指纹来检测文件的内容类型。

       这一整节基于tika和媒体类型注册的导引和记录的信息。

4.3.1文件名

       最简单和广泛的检测文件类型机制是查看文件名。大多数现代的操作系统和程序使用文件扩展名如“.txt or .png”来暗示文件类型,即使这是最不正式的以及没有什么保证扩展名恰好匹配文件的格式。

      

你可以轻松地使用文件扩展名的概念来欺骗你的计算机。例如不管你的系统是Windows还是mac,尝试将一个图片的扩展名改为“.txt”。现在,双击文件。发生什么?你的计算机尝试使用文档编辑器打开这一图片。这个基于文件扩展名的是很容易更改的。一些现代的操作系统试图使用更多的信息而不仅仅是文件扩展名来决定使用什么程序来打开文件。

 

  

 

使用文件扩展名可以追溯到40年前,那时由DEC建造的计算机操作系统开始将文件名分成基本名与类型扩展名。这个开始被其他的供应商采用,包括微软,DOS。现在的微软Windows系统不再限制文件名的长度(实际上限制了文件路径的长度),但是文件扩展名依然是被用来决定哪个程序来处理文件。同样的当前的MAC和Unix系统也这样处理文件。

除了文件扩展名,也有一些更独特的文件名和文件名模式,可以用来识别文件的类型。例如,很多软件项目内含的文本文件README,LICENSE和MakeFile没有任何的文件扩展名。Unix系统广泛使用的配置文件(.*rc),*意味着任意的字符序列。

这些和上千的其他已知的文件名模式与扩展字被tika以<glob pattern=”……”>记录在媒体类型注册中。例如下面的c/c++源文件:

如果你使用特殊的文件格式扩展字,这不是tika已知的,你可以通过更改tika-mimetypes.xml配置文件来扩展tika。增加这一文件的信息在编辑器中修改即可。

4.3.2内容类型提示

有时候文件的文件名不可获取,或者名字缺少类型扩展字。这是很常见的当文件在数据库中时通过网络访问,或者是作为一个文件中的附件的时候。这一情况下,将文件与外部的类型信息联系,最常见的显式媒体类型。

例如网页浏览器使用的http协议中向服务器请求HTML页面和别的文件指定内容类型的头,这个服务器返回对应的文件响应。

另一个例子则是一些程序设置文件的元数据作为内容类型的提示,就像你使用的微软WORD的文件。

4.3.3魔数字节

       文件扩展名和别的内容类型提示通常是相当准确的,但是都没有保证。在一些情况外部的信息不可获取或者是错误的,所以仅有的判断文件的类型的办法是查看文件内部,基于文件的内容检测类型。

       文件格式:一种解释文件中的信息的格式。绝大多数的文件格式有一些独特的特点能够在文件的字节流中被检测到。很多格式甚至引入了魔数字节前缀来作为准确识别文件格式。例如,GIF图像内容总是以ASCII码“GIF87a”或“GIF89a”开头(取决于格式的版本)。

       使用魔数字节作为一种媒体类型检测的方式是非常好的,但这只是问题的一半。另一个则是准确识别文件的编码,也就是前面常提到的charset。

4.3.4字符编码

       在检测复杂的魔数字节,文件扩展名,内容类型提示后,你可以假定至少处理文本文件是很简单的了。文本的主要问题是有很多表示字节的方式。这就叫做字符编码,实际中有很多种不同的编码方式在使用。

       就像前面所讨论的,text/plain媒体类型经常带有charset参数来表示文件的字符编码。即使这些信息是可获取的,但也常常是错误的。更好的检测字符编码的方式是极其需要的。

 

BOMMARKERS

       检测字符编码的最简单的方式是查找可选的字节顺序标记(BOM,byte order mark),这是Unicode编码使用来表明存在于文件的编码顺序。Unicode字符U+FEFF是有目的的转换,被引入作为Unicode编码流的第一个字符。Table4.5展示了BOM如何在常用的Unicode编码中使用。

       如果文件的前一段字节匹配为已知的BOM模式,你可以相对确定的你正在处理的文件的字符编码。除此之外,如果运气不好,因为别的字符编码使用字节顺序标记,这也没有了可靠的简单标记了。

 

BYTEFREQUNENCY

       检测这些文件的类型和编码最好的方法是检查文件前一些的字节中不同字节的频率。纯ASCII文本几乎不包含对字符的控制除了换行与tab,大多数别的字符编码在常见的文本中避免使用这些字节。所以如果你看到很多控制字节(characters with code <32),你可以假定你不是在处理纯文本文件。

       如果文件不像是纯文本,你依然需要判断字符编码。有用于检测编码如utf-8编码时容易辨认出的byte模式的多字节字符编码的技巧,一些未被使用过的某些字节值(例如,ASCII编码仅使用7bits)。

 

STATISTICALMATCHING

       在你已经检查简单的匹配排除不可能的替换之后,最后的重排使用统计匹配来决定字符编码是哪种最可能产出像输入文件的字节与字节序列。很多字符编码与一种或一些特定的语言联系在一起,所以编码的字符频率或者字符对可以用来准确的预测文件使用的语言和编码。

       Tika的MediaTypeRegistry实现所有的检测机制,允许你在程序中去使用。

 

4.3.5其他的机制

     一些文件格式是基于更常见的一般格式(Zip结构,application/zip),XML(application/xml),或者微软的格式,超链接和内嵌的文件。即使是内部文件格式通过魔数字节与其他细节也容易检测出,但却很难确定该格式是否用于宿主更具体的文档格式。需要对容器格式进行解析,以确定内容是否与更具体的文档类型相匹配。

      

XMLFORMAT

       这种格式中最值得注意的是XML,它被用于无数特定的文档类型,如XHTML(application/xhtml+xml)和SVG(image/svg + XML)。为了检测给定XML文档的特定类型,对文档的根元素进行解析,然后与已知的根元素名称和名称空间进行匹配。

 

OLEFORMAT

       微软的OLE格式是另一种麻烦的检测格式。默认情况下,在1995至2003年间发布的所有微软Office版本中,许多仍在生产中使用,OLE格式是地球上使用最广泛的文档格式之一。OLE格式本质上是一个单一文件中的微型文件系统。具体命名的目录和此类文件中的文件条目由特定程序使用,因此可以通过查看OLE容器的目录树来确定文档的类型。不幸的是,OLE格式有点复杂,需要对文档进行随机访问,这使得从Web服务器对正在流媒体的文档进行OLE类型检测是困难的。tika用最省力的方法,即使在这些约束下,也可以很好地用于OLE检测实践中。

 

COMBINEDHEURISTICS

       这些和其他的自定义检测器常常扩展当tika遇到新的文件格式不能通过前面提过的机制检测出来时。

       这是一个负载不同类型检测的机制,没有一个确保准确!面对这样的复杂性,我们只能宣布失败吗?幸运的是,情况不是那么的糟糕,因为前面的许多方法可以独立地用来验证另一种检测方法的结果。然后,通过结合手头上的各种检测方法,我们可以对几乎所有文档的媒体类型进行高度精确的估计。最好的是,tika也自动地为你做了这个。下一节告诉你如何做到的。

 

4.4tika,类型检查者

       就像你在第二章中所记得的,表面的Tika类有一个detect()方法,这个方法返回检测到的指定文件的媒体类型。下面的SimpleTypeDetector类对实际的使用进行展示:

是不是很简单?现在,看看通过类型检测你还能做什么。第一件事情转换自定义的类型注册,其包含了一些你的程序需要的额外类型信息。下面会展示怎么指定一个媒体类型的配置文件给tika使用。默认的类型配置文件资源是在“/org/apache/tika/mime/tika-mimetypes.xml”:

除了传递java.io.File实例给检测方法detect()之外,你也可以以流,URLs,或者文件名的形式传给输入。在以上的每种情况下,tika都会尽可能地组合它自己文件可得到的类型信息与你提供的信息。结果通常是你所期望的类型。

4.5总结

       这使我们关于文件格式分类与相关文件类型的检测方式的讨论完整。我们会通过介绍互联网媒体类型系统和tika使用mime-info数据库,MediaType和MediaTypeRegistry类如何去处理媒体类型为开始。然后学习检测文件类型的几个层次结构,最后返回到tika表层的detect()方法。

       现在,你应该知道不仅仅是如何使用tika检测文件类型,还有tika内部的任务处理结构,以及用自定义的类型信息扩展tika。这些将会在下一章中处理提取信息提供帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值