日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

第七章、epub文件处理 -- 解析 .xhtml文件 (一)

發布時間:2023/12/3 综合教程 36 生活家
生活随笔 收集整理的這篇文章主要介紹了 第七章、epub文件处理 -- 解析 .xhtml文件 (一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

第七章、epub文件處理?--?解析?.xhtml文件?(一)

?

本章將介紹代碼如何利用ZLTextPlainModel類來分別處理.xhtml文件中的文本信息與標簽信息。

本章涉及的核心類是ZLTextPlainModel類、ZLTextWritablePlainModel類、CachedCharStorage類、XHTMLTagAction接口實現類

?.xhtml文件中包含著兩種信息:文本信息與標簽信息。我們需要先正確解析出標簽信息代表的結構,才能正確得將文本信息顯示在屏幕上。

舉個例子:(這個例子是三體1中的文本)

我們需要讓程序知道這里有四種標簽(h1標簽、h2標簽、b標簽、p標簽),每種標簽代表了不同的格式。程序必須正確顯示出不同標簽的格式,才能讓用戶看到正常的文本信息。

在正式開始介紹對.xhtml文件中的文本信息與標簽信息的處理流程之前,我們有必要先來介紹下流程中涉及的三個核心類:ZLTextWritablePlainModel類、CachedCharStorage類、XHTMLTagAction接口實現類

ZLTextWritablePlainModel類:

ZLTextWritablePlainModel類是ZLTextPlainModel類的子類,這個類中有三個int數組與一個CachedCharStorage類。

myStartEntryIndices屬性指向的int數組記錄了每個段落具體在CachedCharStorage類內部的哪一個char數組里面;

myStartEntryOffsets屬性指向的int數組記錄了每個段落從CachedCharStorage類內部char數組的哪個位置開始;

myParagraphLengths屬性指向的int數組記錄每個段落在CachedCharStorage類內部char數組中占據多少長度;

最后,myStorage屬性指向的CachedCharStorage類內部的char數組則是實際存儲文本信息與標簽信息的地方

PS:FBReader程序中一組p標簽就代表一個段落(Paragraph)。

CachedCharStorage類:

這個類中有兩個重要的屬性:myArray屬性、myBlockSize屬性

myArray屬性指向一個由char數組組成的ArrayList(char數組都設定為軟引用WeakReference,保證了虛擬機會回收這些char數組,不會占用過多的內存)。這些char數組里面的元素就代表這.xhtml的文本信息與標簽信息。

myBlockSize屬性指向一個int。char數組的長度最長不會超過這個長度(65536),一旦超過這個長度,代碼就會新建一個char數組,同時就的數組會被持久化以便以后再用。

XHTMLTagAction接口實現類:

epub文件中有很多標簽,不同的標簽代表不同的不同的結構,所以FBReader也為不同的標簽提供了不同的處理類。這些處理類都是XHTMLTagAction接口的實現類。

標簽一般都是成對出現的,XHTMLTagAction接口中的兩個方法分別就對應了

?

具體哪些類對應哪些標簽,是由XHTMLReader類中fillTagTable方法定義的。

?

介紹完三個核心類,我們就可以正式開始介紹對.xhtml文件中的文本信息與標簽信息的處理流程了。

我們先以處理一個標簽對(包含起始標簽和結束標簽)的流程為例。在利用for循環迭代標簽對轉換成的char數組的過程中ZLXMLParser類的doIt方法會對以下的節點調用XHTMLReader類進行操作

起始標簽右邊的“<”:

記錄char數組的偏移量,調用ZLXMLReader接口characterDataHandlerFinal方法(XHTMLReader類并未實現該方法,故可以忽略)

起始標簽右邊的“>”:

記錄char數組的偏移量,取出兩次偏移量當中的內容,得到當前標簽的標簽名。

ZLXMLParser類的processStartTag方法??->??XHTMLReader類的startElementHandler方法??->??XHTMLTagParagraphWithControlAction類的doAtStart方法

結束標簽左邊的“<”:

記錄char數組的偏移量,取出兩次偏移量當中的內容,得到標簽當中的文本信息

XHTMLReader類的characterDataHandler方法??->??BookReader類的addData方法

將標簽當中的文本信息存儲到BookReader類的myTextBuffer屬性

結束標簽右邊的“>”:

ZLXMLParser類的processEndTag方法??->??XHTMLReader類的endElementHandler方法??->??標簽名對應XHTMLTagAction接口實現類的doAtEnd方法

將BookReader類中的myTextBuffer屬性

下面我們再以《三體1》中的一段文本作為例子來詳細介紹下這個流程:

H1標簽處理流程

起始標簽右邊的“<”:

記錄char數組的偏移量

起始標簽右邊的“>”:

記錄char數組的偏移量,取出兩次偏移量當中的內容,得到當前標簽的標簽名。

ZLXMLParser類的processStartTag方法??->??XHTMLReader類的startElementHandler方法??->??XHTMLTagParagraphWithControlAction類的doAtStart方法

doAtStart方法

doAtStart方法會調用了兩個方法BookReader類的pushKind方法與beginParagraph方法

BookReader類的pushKind方法:

這個方法會在myKindStack屬性中添加FBTextKind.H1(31),而其實myKindStack屬性中已經有FBTextKind.REGULAR(0),這個屬性是在OEBBookReader類的readBook方法中設置的。

BookReader類的beginParagraph方法

這個方法調用了ZLTextWritablePlainModel類的createParagraph方法,然后用for循環迭代myKindStack屬性并調用ZLTextWritablePlainModel類的addControl方法


createParagraph方法更新了ZLTextWritablePlainModel類中的三個屬性,以后會依靠這三個屬性在CachedCharStorage類的char數組中快速定位某一個段落

???????? ?

addControl方法往CachedCharStorage類中的char數組加入了兩個可以代表標簽的常量

????????

????????? ??PS:每次調用addControl方法都會加入ZLTextParagraph.Entry.CONTROL3)這個常量,這個常量是一種標示。類似的標示還有常量ZLTextParagraph.Entry.TEXT1),我們會在下一章用到這兩種變量。具體這兩個標示是如何發揮作用的,請參考第十章中的內容。


結束標簽左邊的“<”:

記錄char數組的偏移量,取出兩次偏移量當中的內容,得到標簽當中的文本信息

XHTMLReader類的characterDataHandler方法,將標簽當中的文本信息存儲到myTextBuffer屬性

結束標簽右邊的“>”:

ZLXMLParser類的processEndTag方法??->??XHTMLReader類的endElementHandler方法??->??XHTMLTagParagraphWithControlAction類的doAtEnd方法

doAtEnd方法會調用ZLTextWritablePlainModel類的addText方法,在CachedCharStorage類中的char數組中加入三種信息:

1、常量ZLTextParagraph.Entry.TEXT(1),這是一種標示,類似常量ZLTextParagraph.Entry.CONTROL(3)

2、標簽間文本信息的長度

3、標簽間的實際文本信息

????

H2標簽、P標簽與H1標簽基本上是一樣,唯一的區別在于在起始標簽右邊的“>”觸發的addControl方法中加入不同的常量,而這個變量其實是在FBTextKind接口中定義的。

H2標簽會加入FBTextKind.REGULAR(0)以及FBTextKind.H2(32),P標簽則只會加入FBTextKind.REGULAR(0)。每次加入這些常量的時候都會同時加入作為標示的常量ZLTextParagraph.Entry.TEXT(1)。

B標簽與其他三個標簽不同,這個標簽會觸發兩次addControl方法,只是兩次的參數不同。

CachedCharStorage類中新增char數組

這里需要補充下CachedCharStorage類中新增char數組的流程,我們在介紹CachedCharStorage類的時候,曾經講過:“BookModel類中的myBlockSize屬性指向一個int。char數組的長度最長不會超過這個int(65536),一旦超過這個長度,代碼就會新建一個char數組,同時就的數組會被持久化以便以后再用?!?

新增char數組的工作由CachedCharStorage的createNewBlock方法完成

將舊的char數組持久化的工作是在CachedCharStorage類的freezeLastBlock方法完成的。

在sd卡上的Books/.FBReader這個文件夾里面,我們可以找到這些持久化了的文件。

這個位置是在BookModel的構建函數中用過Paths類獲得的。

其實我們可以嘗試把持久化char數組的方法改為utf8的編碼,然后在把得到的文件后綴名改成.txt

打開這個txt文件,我們就可以看到下面這樣的數據

對比原先的xml文件,那些奇怪的符號就代表了標簽信息

好,至此為止,我們將.xhtml文件中的文本信息與標簽信息存儲到了ZLTextPlainModel中。而要想讓程序最終用中正確的格式顯示文本信息,還需要配合之后第八章(定位指定段落)以及第九章(顯示.html文件)的內容才能讓用戶看到格式正確的文本。

題外話

最后,插幾句題外話,寫一些自己的思考:

FBReader使用char數組的形式來存儲xml文件內容與結構信息,然后依靠記錄每個段落在char數組中具體位置的int數組快速獲取指定段落在char數組中的部分。選擇數組是ok的,在數組中定位到某一個部分,速度還是比較快的,但是同時,也因為使用了數組這個數據結構,程序也是相對來說比較占用內存的。一般來說,電子書都是從一整段數據中按順序取出一部分數據顯示在屏幕上,這種業務需求其實用樹的數據結構也是非常合適的。而說到樹的數據結構,其實Android手機中正好有一個現成的sqlite數據庫可以提供這種樹的數據結構。我們可以試想一下,如果改用sqlite數據庫來存儲和檢索xml文件的內容與結構信息的話,相比數組會有怎樣的好處。我想最起碼會有三個好處:第一、節省手機的內存,sqlite數據庫做好索引之后,無需像數組那樣把數據全部裝進內存后才能檢索。這樣一來,程序就節省了內存;二、方便跨平臺的開發,sqlite支持linux、IOS以及HTML5,如果使用sqlite來作為存儲和檢索xml文件的方式,那么Android程序員、IOS程序員以及pc前端程序員只需要根據約定的sql語句就能完成開發,而不必獨立開發三種語言,或者用c或c++另外再開發一個底層庫;三、方便與服務器端對接,當需要對客戶端用戶的閱讀記錄進行收集與分析的時候,如果客戶端與服務端使用同一種或相近的sql結構的話,那么對接的難度就會降低很多。

轉載于:https://my.oschina.net/u/938986/blog/335919

創作打卡挑戰賽贏取流量/現金/CSDN周邊激勵大獎

總結

以上是生活随笔為你收集整理的第七章、epub文件处理 -- 解析 .xhtml文件 (一)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。