第六章、epub文件处理 -- 解析container文件与.opf文件
2019獨角獸企業重金招聘Python工程師標準>>>
第六章、epub文件處理?--?解析container文件與.opf文件
?
這一章我們會接著第三章結尾介紹的FBReaderApp類的openBookInternal繼續,開始介紹解析container文件與.opf文件。
這一章中會涉及到第二章、第四章、第五章中介紹的內容,大家可以互相參照,加深理解
首先,我們來回顧下第四章“epub文件處理?--?epub文件內部組成”的內容。我們在第四章中曾經介紹過,epub文內部包含的文件包括“container.xml文件、.opf文件、.ncx文件、.xhtml文件”。這些文件都是被壓縮過的xml文件,而在這些不同的xml文件中包含著不同的標簽,每種標簽又都代表著不同的信息。為了對每種xml文件的標簽作統一處理,FBReader程序對每種文件都設置了對應的類。每種類就專門處理來對應的xml文件里面的標簽。
ContainerFileReader類對應container.xml文件;OEBBookReader類對應.opf文件; NCXReader類對應.ncx文件文件;XHTMLReader類對應.xhtml文件。
PS:這些類都是ZLXMLReaderAdapter抽象類的子類,本章會涉及到ContainerFileReader類與OEBBookReader類
我們在第四章中還曾經分別介紹過container文件與.opf文件分別的作用。
container文件的“作用就是標明了.opf文件的位置”;.opf文件則描述了epub書籍的元信息、epub文件內部對應不同章節對應的文件的位置以及每個章節出現的先后次序。
我們這一章解析這兩種文件,就是為了獲取這些信息。
在介紹解析流程之前,我們還需要再回顧下解析xml文件的三個核心類。這個部分內容,我們曾經在第二章“解析資源文件”中介紹過。當時,我們是這么介紹的:“
繼續回到解析xml文件的核心類ZMLZMLProcessor、ZLXMLParser、ZLXMLReader。
這三個核心類的調用順序一般是這樣的:
?1、ZLXMLReaderAdapter抽象類的子類(ResourceTreeReader類)里面的read方法調用ZLXMLProcessor類的read方法
2、ZLXMLProcessor類的read方法通過AndroidAssetsFile類(ZLResourceFile類的子類)的getInputStream方法獲取一個針對資源文件的字節流類(AssetInputStream類),并以這個字節流類為參數初始化了一個針對資源文件的字符流類。接著,就調用了ZLXMLParser類的doIt方法。
3、?ZLXMLParser類的doIt方法利用字符流類將文件轉換成一個char數組。再利用for循環迭代byte數組的過程中,doIt方法又反過來調用ZLXMLReader接口實現類(ResourceTreeReader類)的startElementHandler與endElementHandler方法對byte數組中元素所代表的不同節點進行操作。
?
請注意,上面這段話標紅的部分,這些部分在解析epub內部文件的流程中已經不適用了。
1、ZLXMLReaderAdapter抽象類的子類(ContainerFileReader類、OEBBookReader類、NCXReader類、XHTMLReader類中的一種)里面的read方法調用ZLXMLProcessor類的read方法
2、ZLXMLProcessor類的read方法通過ZLZipEntryFile類的getInputStream方法和ZLZipEntryFile類對應的LocalFileHeader類獲取一個針對epub內部xml文件的字節流類(ZipInputStream類),并以這個字節流類為參數初始化了一個針對資源文件的字符流類。接著,就調用了ZLXMLParser類的doIt方法。
3、?ZLXMLParser類的doIt方法利用字符流類將文件轉換成一個char數組(第五章用一整個章節介紹了這個轉換的流程)。再利用for循環迭代byte數組的過程中,doIt方法又反過來調用ZLXMLReader接口實現類(ResourceTreeReader類)的startElementHandler與endElementHandler方法對byte數組中元素所代表的不同節點進行操作。
首先,“ZLXMLReaderAdapter抽象類的子類”已經不再是那個ResourceTreeReader類了,而是專門對應epub內部各種xml文件的一個類(ContainerFileReader類、OEBBookReader類、NCXReader類、XHTMLReader類中的一種)。
PS:ResourceTreeReader類是程序專門為處理資源文件內部的標簽而創建的類
其次,程序在解析epub內部xml文件的時候,不會去獲取“針對資源文件的字節流類”,而是會通過調用ZLZipEntryFile類的getInputStream方法獲取針對epub內部xml文件的字節流類(ZipInputStream類)。相對得,之后也會以這個字節流類來獲得對應的字符流類。
PS:ZLZipEntryFile類的getInputStream方法的具體處理流程我們曾經用了第五章“XML文件處理?--?解壓”一整章來作介紹
好了,下面我們就正式開始解析流程。
?
FBReaderApp類的openBookInternal方法中會調用BookModel類的createModel方法。
crateModel方法,會調用PluginCollection類的getPlugin方法
getPlugin方法調用了所有FormatPlugin抽象類子類的acceptsFile方法,這個方法其實就是比較了Book類中File屬性指向的File類的myExtension屬性(這個屬性的賦值我們在第三章“獲取書籍信息”中介紹過),如果myExtension屬性代碼內置的變量相同,getPlugin方法就會返回當前的FormatPlugin抽象類子類。而在處理epub文件時,代碼會返回OEBPlugin類。
OEBPlugin類readModel方法
獲得了OEBPlugin類之后,代碼就會調用該類中的readModel方法。
readModel方法調用了兩個方法:OEBPlugin類的getOpfFile方法與OEBBookReader類readBook方法
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內部文件的流程”吧。
1、ZLXMLReaderAdapter抽象類的子類(ContainerFileReader類、OEBBookReader類、NCXReader類、XHTMLReader類中的一種)里面的read方法調用ZLXMLProcessor類的read方法
2、ZLXMLProcessor類的read方法通過ZLZipEntryFile類的getInputStream方法和ZLZipEntryFile類對應的LocalFileHeader類獲取一個針對epub內部xml文件的字節流類(ZipInputStream類),并以這個字節流類為參數初始化了一個針對資源文件的字符流類。接著,就調用了ZLXMLParser類的doIt方法。
3、?ZLXMLParser類的doIt方法利用字符流類將文件轉換成一個char數組(第五章用一整個章節介紹了這個轉換的流程)。再利用for循環迭代byte數組的過程中,doIt方法又反過來調用ZLXMLReader接口實現類(ResourceTreeReader類)的startElementHandler與endElementHandler方法對byte數組中元素所代表的不同節點進行操作。
在這個解析流程中, .opf 文件的位置信息會被存儲到 ContainerFileReader 類的 myRootPath 屬性( 35 行)
第三步
代碼以包含.opf的位置信息的String為參數又調用了ZLFile類的createFile方法,這個方法會返回代表.opf文件的ZLZipEntryFile類,獲取這個類之后,代碼會進入OEBBookReader類readBook方法
OEBBookReader類readBook方法:
這個方法分為兩步:第一步、更新myHtmlFileNames屬性;第二步、for循環迭代myHtmlFileNames屬性指向的ArrayList,解析xhtml文件。第一步
更新myHtmlFileNames屬性
OEBBookReader類的read方法更新了myHtmlFileNames屬性。
OEBBookReader類的read方法用讓代碼進入了解析xml文件的流程:
1、ZLXMLReaderAdapter抽象類的子類(ContainerFileReader類、OEBBookReader類、NCXReader類、XHTMLReader類中的一種)里面的read方法調用ZLXMLProcessor類的read方法
2、ZLXMLProcessor類的read方法通過ZLZipEntryFile類的getInputStream方法和ZLZipEntryFile類對應的LocalFileHeader類獲取一個針對epub內部xml文件的字節流類(ZipInputStream類),并以這個字節流類為參數初始化了一個針對資源文件的字符流類。接著,就調用了ZLXMLParser類的doIt方法。
3、?ZLXMLParser類的doIt方法利用字符流類將文件轉換成一個char數組(第五章用一整個章節介紹了這個轉換的流程)。再利用for循環迭代char數組的過程中,doIt方法又反過來調用ZLXMLReader接口實現類(ResourceTreeReader類)的startElementHandler與endElementHandler方法對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類的startElementHandler與endElementHandler方法對byte數組中元素所代表的不同節點進行操作。
對xhtml文件中各節點的操作比container.xml與.opf文件的操作要復雜很多,我們將用兩個章節來介紹。
轉載于:https://my.oschina.net/u/938986/blog/335878
總結
以上是生活随笔為你收集整理的第六章、epub文件处理 -- 解析container文件与.opf文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: div border-radius
- 下一篇: linux第一季运维001