第八章、epub文件处理 -- 定位指定段落

第八章、epub文件处理 -- 定位指定段落

 

上一章中咱们介绍了用ZLTextPlainModel类里的char数组存储.xhtml文件中的文本信息以及标签信息的流程。 html

本章中咱们将介绍从ZLTextPlainModel类里的char数组中定位指定段落的流程。 数组

 

本章涉及的核心类是Processor类(ZLTextParagraphCursor类内部类)、EntryIteratorImpl类(ZLTextPlainModel类内部类) 函数

 

定位到指定段落须要两个方法互相配合:ZLTextParagraphCursor类的cursor方法和ZLTextPage类的moveStartCursor方法 spa

ZLTextParagraphCursor类的cursor方法负责填充表明指定段落的ZLTextParagraphCursor类。在这个过程当中,char数组中表明指定段落的部分转换成一个由ZLTextElement类组成的ArrayList。其中,段落中的文本信息会被转换成ZLTextElement类的子类ZLTextWord,而段落中的标签信息会被转换成ZLTextElement类的子类ZLTextControlElement orm

ZLTextPage类的moveStartCursor方法负责定位到指定的段落。定位的过程主要是维护ZLTextPage类中的StartCursor属性指向的ZLTextWordCursor类。ZLTextWordCursor类中的三个属性myParagraphCursormyElementIndexmyCharIndex结合起来就完成来了定位到指定段落的流程。这三个属性中,myParagraphCursor属性指向的就是表明指定段落的ZLTextParagraphCursor类。 htm

 

当定位流程完成以后,char数组中涉及当前段落的部分会被转换成一个由ZLTextElement子类组成的ArrayList中。这个ArrayList存储在ZLTextParagraphCursor类中的myElements属性中。而同时,ZLTextParagraphCursor这个类又存储在ZLTextPage类的StartCursor属性中。 索引

PS:整个定位流程其实也能够当作ZLTextElement子类 -> ZLTextParagraphCursormyElements属性 -> ZLTextPageStartCursor属性不断上推的过程。 内存

 

下面咱们结合ZLTextViewsetModel方法详细介绍下调用这两个方法定位到定段落的具体流程: get



ZLTextParagraphCursor类 cursor方法

cursor方法的第一个参数为解析xhtml文件获得的ZLTextPlainModel类(第七章中有详细介绍),第二个参数为当前要显示的段落的索引(初始时这个索引为0 it

接着cursor方法以一样的参数调用了ZLTextParagraphCursor类的构造函数


ZLTextParagraphCursor构造函数

    ZLTextParagraphCursor构造函数调用了本类的fill方法,这个方法首先调用了ZLTextPlainModel类的getParagraph方法,接着又调用了Processor类的fill方法

ZLTextPlainModel类的getParagraph方法:

这个方法的做用是初始化了一个ZLTextParagraphImpl类,并定义了这个类中的myModel属性(指向ZLTextPlainModel)与myIndex属性(当前要显示的段落的索引)

        


Processor类(ZLTextParagraphCursor内部类)fill方法

这个方法将最终完成将char数组中表明当前段落的部分转换成一个元素为ZLTextElement类的ArrayList的工做。

方法大体流程是:首先经过EntryIteratorImpl类的构造方法得到正在处理的段落具体在char数组的哪一个部分(67行)。而后,利用EntryIteratorImplnext方法在char数组的这个部分里面不断读取内容并进行操做(71行)。操做分为针对文本信息(75行)和针对标签信息(84行)两种。线面在详细描述着两个方法。

    


    EntryIteratorImpl类(ZLTextPlainModel内部类)构造函数

    这个构造方法的做用就是利用当前段落的索引从ZLTextPlainModel类的三个属性指向的int数组中的当前段落在char数组的哪一部分中。
    这三个属性咱们已经在第七章中有介绍过了。
    myStartEntryIndices属性指向的int数组记录了每一个段落具体在CachedCharStorage类内部的哪个char数组里面;
    myStartEntryOffsets属性指向的int数组记录了每一个段落从CachedCharStorage类内部char数组的哪一个位置开始;
    myParagraphLengths属性指向的int数组记录每一个段落在CachedCharStorage类内部char数组中占据多少长度;


    EntryIteratorImpl类(ZLTextPlainModel内部类)next方法

    这个方法会在char数组的表明当前段落的部分里面不断读取内容并进行操做。

    在读取的过程当中首先会经过CachedCharStorage类的block方法获取对应须要显示的段落的char数组(125行),获取对应的char数组以后,代码就会利用不断递增的dataOffset变量,不断读取char数组中的内容。一旦代码读取到表明文本信息或标签信息的标示,就会进入不一样的流程。

    PS:咱们曾在上一章中介绍过这两种标示,当时咱们是这么介绍的:“每次调用addControl方法都会加入ZLTextParagraph.Entry.CONTROL3)这个常量,这个常量是一种标示。相似的标示还有常量ZLTextParagraph.Entry.TEXT1),咱们会在下一章用到这两种变量”。

    

    CachedCharStorage类的block方法:

    咱们在上一章中介绍CachedCharStorage类的时候,曾经说过“char数组的长度最长不会超过这个长度(65536),一旦超过这个长度,代码就会新建一个char数组,同时旧的数组会被持久化以便之后再用。”因此当前在内存中的char数组不必定会包含须要显示的数组,若是不包含须要显示的数组就须要根据ZLTextWritablePlainModel类的myStartEntryIndices属性找到对应的char数组。(这个属性的具体介绍也能够在上一章中找到)

    获取到包含须要显示的段落的char数组后,代码就会利用不断递增的dataOffset变量,不断读取char数组中的内容。一旦代码读取到表明文本信息或标签信息的标示,就会进入不一样的流程。   

         

    获取到包含须要显示的段落的char数组后,代码就会利用不断递增的dataOffset变量,不断读取char数组中的内容。一旦代码读取到表明文本信息或标签信息的标示,就会进入不一样的流程。


    文本信息(ZLTextParagraph.Entry.TEXT

    遇到表明文本的ZLTextParagraph.Entry.TEXT标示的状况:

    这种状况下,代码会对分在这个标示以后的文本信息会进行两部分处理,一部分处理在EntryIteratorImplnext方法中进行,一部分在Processor类的fill方法中进行

    在EntryIteratorImplnext方法中,会赋值两个EntryIteratorImpl类的两个变量。myTextLength属性记录文本信息的长度,myTextData属性存储当前char数组的引用。最后还经过赋值dataOffset,在char数组中向前跳过了涉及这段文本信息的部分。

    

    在Processorfill方法会调用本类的processTextEntry方法

    

    在processTextEntry方法中代码利用一个for循环,一个一个读取char数组中的元素,而后对每一个元素调用Processor类的addWord方法。请注意,调用addWord方法时的参数。

    

    addWord方法会初始化一个ZLTextWord类,而后将这个类加入ZLTextParagraphCursormyElements属性指向的ArrayList

    
    
请注意对比下ZLTextWord类构造函数与调用addWord方法时的参数
    


    标签信息(ZLTextParagraph.Entry.CONTORL

遇到表明文本的ZLTextParagraph.Entry.CONTORL标示的状况:

这种状况下,代码一样也会对跟在这个标示以后的标签信息会进行两部分处理,一部分处理在EntryIteratorImplnext方法中进行,一部分在Processor类的fill方法中进行

EntryIteratorImplnext方法会赋值三个属性,请尤为注意下myControlIsStart这个属性,咱们会在处理样式的时候用到这个属性。

    

    Processor类的fill方法会初始化一个ZLTextWord类,而后将这个类加入ZLTextParagraphCursormyElements属性指向的ArrayList

当代码从ZLTextParagraphCursor类 cursor方法返回是,咱们会获得新建的ZLTextParagraphCursor类,这个类中的myElements属性指向的ArrayList已经被填充了表明当前段落中文本信息的ZLTextWord类与标签信息的ZLTextControlElement类。接着就会进入ZLTextPage类的moveStartCursor方法。


ZLTextPage类的moveStartCursor方法

这个方法比较简单,其实就是将经过ZLTextParagraphCursor类的cursor方法填充好的ZLTextParagraphCursor类,赋值给ZLTextPage类内的StartCursor属性

同时,ZLTextPage类内的StartCursor属性指向的ZLTextWordCursor类进行下设置


完成moveStartCursor方法后,咱们就完成“定位指定段落”的流程了。

相关文章
相关标签/搜索