第六章、epub文件处理 -- 解析container文件与.opf文件

第六章、epub文件处理 -- 解析container文件与.opf文件

 

这一章咱们会接着第三章结尾介绍的FBReaderApp类的openBookInternal继续,开始介绍解析container文件与.opf文件。 html

这一章中会涉及到第二章、第四章、第五章中介绍的内容,你们能够互相参照,加深理解 数组

首先,咱们来回顾下第四章“epub文件处理 -- epub文件内部组成”的内容。咱们在第四章中曾经介绍过,epub文内部包含的文件包括“container.xml文件、.opf文件、.ncx文件、.xhtml文件”。这些文件都是被压缩过的xml文件,而在这些不一样的xml文件中包含着不一样的标签,每种标签又都表明着不一样的信息。为了对每种xml文件的标签做统一处理,FBReader程序对每种文件都设置了对应的类。每种类就专门处理来对应的xml文件里面的标签。 spa


ContainerFileReader类对应container.xml文件;OEBBookReader类对应.opf文件; NCXReader类对应.ncx文件文件;XHTMLReader类对应.xhtml文件。 orm

PS:这些类都是ZLXMLReaderAdapter抽象类的子类,本章会涉及到ContainerFileReader类与OEBBookReader xml

咱们在第四章中还曾经分别介绍过container文件与.opf文件分别的做用。 htm

container文件的“做用就是标明了.opf文件的位置”;.opf文件则描述了epub书籍的元信息、epub文件内部对应不一样章节对应的文件的位置以及每一个章节出现的前后次序。 接口

咱们这一章解析这两种文件,就是为了获取这些信息。 ip



在介绍解析流程以前,咱们还须要再回顾下解析xml文件的三个核心类。这个部份内容,咱们曾经在第二章“解析资源文件”中介绍过。当时,咱们是这么介绍的:“ 资源

继续回到解析xml文件的核心类ZMLZMLProcessorZLXMLParserZLXMLReader get

这三个核心类的调用顺序通常是这样的:

 1ZLXMLReaderAdapter抽象类的子类ResourceTreeReader类)里面的read方法调用ZLXMLProcessor类的read方法

2ZLXMLProcessor类的read方法经过AndroidAssetsFile类(ZLResourceFile类的子类)getInputStream方法获取一个针对资源文件的字节流类(AssetInputStream类),并以这个字节流类为参数初始化了一个针对资源文件的字符流类。接着,就调用了ZLXMLParser类的doIt方法。

3、 ZLXMLParser类的doIt方法利用字符流类将文件转换成一个char数组。再利用for循环迭代byte数组的过程当中,doIt方法又反过来调用ZLXMLReader接口实现类(ResourceTreeReader类)的startElementHandlerendElementHandler方法对byte数组中元素所表明的不一样节点进行操做。

 

请注意,上面这段话标红的部分,这些部分在解析epub内部文件的流程中已经不适用了。

1ZLXMLReaderAdapter抽象类的子类ContainerFileReader类、OEBBookReader类、NCXReader类、XHTMLReader类中的一种)里面的read方法调用ZLXMLProcessor类的read方法

2ZLXMLProcessor类的read方法经过ZLZipEntryFilegetInputStream方法和ZLZipEntryFile类对应的LocalFileHeader获取一个针对epub内部xml文件的字节流类(ZipInputStream类),并以这个字节流类为参数初始化了一个针对资源文件的字符流类。接着,就调用了ZLXMLParser类的doIt方法。

3、 ZLXMLParser类的doIt方法利用字符流类将文件转换成一个char数组(第五章用一整个章节介绍了这个转换的流程)。再利用for循环迭代byte数组的过程当中,doIt方法又反过来调用ZLXMLReader接口实现类(ResourceTreeReader类)的startElementHandlerendElementHandler方法对byte数组中元素所表明的不一样节点进行操做。

首先,“ZLXMLReaderAdapter抽象类的子类”已经再也不是那个ResourceTreeReader类了,而是专门对应epub内部各类xml文件的一个类(ContainerFileReader类、OEBBookReader类、NCXReader类、XHTMLReader类中的一种)。

PSResourceTreeReader类是程序专门为处理资源文件内部的标签而建立的类

其次,程序在解析epub内部xml文件的时候,不会去获取“针对资源文件的字节流类”,而是会经过调用ZLZipEntryFile类的getInputStream方法获取针对epub内部xml文件的字节流类(ZipInputStream类)。相对得,以后也会以这个字节流类来得到对应的字符流类。

PSZLZipEntryFile类的getInputStream方法的具体处理流程咱们曾经用了第五章“XML文件处理 -- 解压”一整章来做介绍



好了,下面咱们就正式开始解析流程。

 

FBReaderApp类的openBookInternal方法中会调用BookModel类的createModel方法。


crateModel方法,会调用PluginCollection类的getPlugin方法

getPlugin方法调用了全部FormatPlugin抽象类子类的acceptsFile方法,这个方法其实就是比较了Book类中File属性指向的File类的myExtension属性(这个属性的赋值咱们在第三章“获取书籍信息”中介绍过),若是myExtension属性代码内置的变量相同,getPlugin方法就会返回当前的FormatPlugin抽象类子类。而在处理epub文件时,代码会返回OEBPlugin类。




OEBPluginreadModel方法

得到了OEBPlugin类以后,代码就会调用该类中的readModel方法。



readModel方法调用了两个方法:OEBPlugin类的getOpfFile方法与OEBBookReaderreadBook方法



OEBPlugin类的getOpfFile方法:

getOpfFile方法一共有三步:

第一步    

调用ZLFile类的createFile方法

这个方法的参数oebFile参数是Book类的File属性(这个属性的赋值过程在第三章“获取书籍信息”介绍过),最终这个方法会返回一个表明container.xml文件的ZLZipEntryFile类。

咱们曾经在第二章“解析资源文件”中介绍过:“ZLZipEntryFile类用来处理epub文件内部的xml文件”。也曾经在第四章“epub文件处理 -- epub文件内部组成”介绍过container.xml文件,这个文件的做用就是“标明了.opf文件的位置”。

咱们从代码中能够看到,表明container.xml文件的ZLZipEntryFile会包含两个属性(85行):一个表明epub文件的ZLPhysicalFile类,一个表明epub内部xml文件名种子的String变量(在这里就是)。


第二步

ContainerFileReader类的read方法。

看到这个方法,你应该会记起这一章开头介绍的“解析epub内部文件的流程”吧。

1ZLXMLReaderAdapter抽象类的子类(ContainerFileReader类、OEBBookReader类、NCXReader类、XHTMLReader类中的一种)里面的read方法调用ZLXMLProcessor类的read方法

2ZLXMLProcessor类的read方法经过ZLZipEntryFile类的getInputStream方法和ZLZipEntryFile类对应的LocalFileHeader类获取一个针对epub内部xml文件的字节流类(ZipInputStream类),并以这个字节流类为参数初始化了一个针对资源文件的字符流类。接着,就调用了ZLXMLParser类的doIt方法。

3、 ZLXMLParser类的doIt方法利用字符流类将文件转换成一个char数组(第五章用一整个章节介绍了这个转换的流程)。再利用for循环迭代byte数组的过程当中,doIt方法又反过来调用ZLXMLReader接口实现类(ResourceTreeReader类)的startElementHandlerendElementHandler方法对byte数组中元素所表明的不一样节点进行操做。

           在这个解析流程中, .opf 文件的位置信息会被存储到 ContainerFileReader 类的 myRootPath 属性( 35 行)



第三步

代码以包含.opf的位置信息的String为参数又调用了ZLFile类的createFile方法,这个方法会返回表明.opf文件的ZLZipEntryFile类,获取这个类以后,代码会进入OEBBookReaderreadBook方法


OEBBookReaderreadBook方法:

这个方法分为两步:第一步、更新myHtmlFileNames属性;第二步、for循环迭代myHtmlFileNames属性指向的ArrayList,解析xhtml文件。

第一步

更新myHtmlFileNames属性

OEBBookReader类的read方法更新了myHtmlFileNames属性。


OEBBookReader类的read方法用让代码进入了解析xml文件的流程:

1ZLXMLReaderAdapter抽象类的子类(ContainerFileReader类、OEBBookReader类、NCXReader类、XHTMLReader类中的一种)里面的read方法调用ZLXMLProcessor类的read方法

2ZLXMLProcessor类的read方法经过ZLZipEntryFile类的getInputStream方法和ZLZipEntryFile类对应的LocalFileHeader类获取一个针对epub内部xml文件的字节流类(ZipInputStream类),并以这个字节流类为参数初始化了一个针对资源文件的字符流类。接着,就调用了ZLXMLParser类的doIt方法。

3、 ZLXMLParser类的doIt方法利用字符流类将文件转换成一个char数组(第五章用一整个章节介绍了这个转换的流程)。再利用for循环迭代char数组的过程当中,doIt方法又反过来调用ZLXMLReader接口实现类(ResourceTreeReader类)的startElementHandlerendElementHandler方法对byte数组中元素所表明的不一样节点进行操做。

咱们曾经在第四章“epub文件处理 -- epub文件内部组成”中介绍过.opf文件中的“manifest节点的做用是描述epub文件内部对应不一样章节对应的文件的位置”。


咱们如今就是要把这些位置信息存储到myHtmlFileNames属性指向的ArrayList中。而这个工做是OEBBookReader类的startElementHandler方法中完成的。


第二步

for循环迭代myHtmlFileNames属性指向的ArrayList,解析xhtml文件

ZLFile类的createFileByPath方法会生成表明xhtml文件的ZLZipEntryFile类。以后XHTMLReader类的readFile方法会开始对xhtml文件的解析。


XHTMLReader类的readFile方法会调用本类的read方法。这个方法又会让代码进入解析xml文件的流程。这个流程咱们在本章中已经屡次遇到了。走完这个流程,咱们就会获得一个有xml文件转换成的char数组。代码循环迭代这个char数组,调用XHTMLReader类的startElementHandlerendElementHandler方法对byte数组中元素所表明的不一样节点进行操做。


xhtml文件中各节点的操做比container.xml.opf文件的操做要复杂不少,咱们将用两个章节来介绍。

相关文章
相关标签/搜索