发明内容
有鉴于此,本发明的目的在于,提出一种读取FAT磁盘文件的方法和装置,可以占用较小内存实现快速读取FAT磁盘文件。
本发明实施例提出一种读取FAT磁盘文件的方法,包括如下步骤:
在内存中保存如下内容:全分区最小索引号及该索引号对应文件的全位置信息;全分区最大索引号及该索引号对应文件的文件全位置信息;序列元素对应的最大索引号及该索引号对应文件的文件全位置信息;以及序列元素对应的最小索引号及该索引号对应文件的文件全位置信息;所述文件全位置信息包括文件目录项位置信息、文件目录项在其所在目录的目录项中的位置偏移以及文件所在目录的簇号;
预先对FAT格式的磁盘分区中特定类型的文件进行全分区搜索,为每一个搜索到的文件分配唯一的索引号;在内存中保存N个索引号连续的文件目录项位置信息的序列;N为自然数;
判断所要读取的文件索引号i是否在序列元素对应的最小索引号到序列元素对应的最大索引号的范围内,若是,则从序列元素中找到索引号i对应的文件目录项位置信息,并根据所找到的文件目录项位置信息读取所述磁盘分区上的文件;
否则,在全分区最小索引号、全分区最大索引号、序列元素对应的最大索引号和序列元素对应的最小索引号这四个索引号之间取与i的差值最小的索引号,计为k,并以索引号k对应的文件的全位置信息为起点确定搜索方向;
以索引号k对应的文件的全位置信息为起点,以所确定的搜索方向进行所述类型文件的部分搜索,搜索到包含索引号i的连续的N个索引号,将所搜索到的N个索引号对应的目录项位置信息保存为序列元素;并根据所保存的序列元素中、索引号i对应的文件目录项位置信息读取所述磁盘分区上的文件。
所述为每一个搜索到的文件分配唯一的索引号为:按照搜索结果的顺序号作为该文件的索引号。
所述序列的维数为2的正整数幂次。
所述以索引号k对应的文件的全位置信息为起点确定搜索方向包括:
比较索引号i与索引号k的大小,当i<k时向全分区搜索的相反方向执行部分搜索,否则向全分区搜索的相同方向执行部分搜索。
所述包含索引号的连续的N个索引号为:
索引号从i到i+N-1的N个索引号;
或者,将索引号从i-(N/2)到i+(N/2)-1的N个索引号。
所述以索引号k对应的文件的全位置信息为起点,以所确定的搜索方向进行所述类型文件的部分搜索的步骤包括:
判断所搜索到的N个索引号中的最小索引号M1是否小于内存中已保存的序列元素对应的最小索引号,若是,则将M1保存为新的序列元素对应的最小索引号,以内存中已保存的全分区最小索引号对应文件的全位置信息为起点,向全分区搜索的相同方向搜索所述类型文件;
或者,判断所搜索到的N个索引号中的最大索引号M2是否大于内存中已保存的序列元素对应的最大索引号,若是,则将M2保存为新的序列元素对应的最大索引号,以内存中已保存的全分区最大索引号对应文件的全位置信息为起点,向全分区搜索的相反方向搜索所述类型文件。
其特征在于,所述以索引号k对应的文件的全位置信息为起点,以所确定的搜索方向进行所述类型文件的部分搜索,搜索到包含索引号i的连续的N个索引号包括:
在已保存的文件目录项位置信息中查找是否有需要保留的内容,若是,则跳过所述需要保留的内容,并更新其余的文件目录项位置信息。
本发明实施例还提出一种读取FAT磁盘文件的装置,包括:全分区搜索模块、存储模块、读取模块和部分搜索模块;
全分区搜索模块,用于对FAT格式的磁盘分区中特定类型的文件进行全分区搜索,为每一个搜索到的文件分配唯一的索引号;
存储模块,包括N维的序列存储单元,所述序列存储单元用于保存所述全分区搜索模块搜索到的N个索引号连续的文件目录项位置信息;根据来自部分搜索模块的索引号i及其附近共N个文件的目录项位置信息,对所保存的文件目录项信息进行更新;所述存储模块保存全分区最小索引号及该索引号对应文件的全位置信息;全分区最大索引号及该索引号对应文件的文件全位置信息;序列元素对应的最大索引号及该索引号对应文件的文件全位置信息;以及序列元素对应的最小索引号及该索引号对应文件的文件全位置信息;所述文件全位置信息包括文件目录项位置信息、文件目录项在其所在目录的目录项中的位置偏移以及文件所在目录的簇号;
读取模块,用于判断所要读取的文件的索引号i是否在存储模块保存序列元素对应的最小索引号到序列元素对应的最大索引号的范围内,若是,则从序列元素中找到索引号i对应的文件目录项位置信息,并根据所找到的文件目录项位置信息读取所述磁盘分区上的文件;否则,在全分区最小索引号、全分区最大索引号、序列元素对应的最大索引号和序列元素对应的最小索引号这四个索引号之间取与i的差值最小的索引号,计为k,并以索引号k对应的文件的全位置信息为起点确定搜索方向,将索引号k与所确定的索引方向发送至部分搜索模块;待存储模块存储的内容更新后,从序列存储单元中找到索引号i对应的文件目录项位置信息,并根据所找到的文件目录项位置信息读取所述磁盘分区上的文件;
部分搜索模块用于以来自读取模块的搜索起点为起点,以读取模块所确定的搜索方向进行部分搜索,将搜索到的索引号i及其附近共N个文件的目录项位置信息发送至存储模块。
所述读取模块进一步包括:
搜索方向确定单元,用于比较所述索引号k和i的大小,当i<k时,确定搜索方向为全分区搜索的相反方向,否则确定搜索方向为全分区搜索的相同方向。
较佳地,所述装置进一步包括:
边界调整模块,用于判断部分搜索模块所搜索到的N个索引号中的最小索引号M1是否小于存储模块中已保存的序列元素对应的最小索引号,若是,则通知所述部分搜索模块以存储模块中已保存的全分区最小索引号对应文件的全位置信息为起点;
或者,用于判断部分搜索模块所搜索到的N个索引号中的最大索引号M2是否大于存储模块中已保存的序列元素对应的最大索引号,若是,则通知所述部分搜索模块以存储模块中已保存的全分区最大索引号对应文件的全位置信息为起点从以上技术方案可以看出,由于全分区搜索产生的文件目录项信息的数目太大,本发明方案通过设定一定大小的内存空间来存储一小段连续的索引号及文件目录项位置信息,在此基础上通过部分搜索的方式找到目标文件的文件目录项位置信息。内存空间大小可以根据实际内存需求以及***的运行速度调整,从而可以在占用较小内存空间的情况下快速读取FAT磁盘文件。
具体实施方式
为使本发明的目的、技术方案和优点更加清楚,下面结合附图对本发明作进一步的详细阐述。
一个FAT磁盘文件的大小、创建时间、文件数据所在的起始位置即首簇号信息都是记录在文件目录项中,文件目录项的长度为32字节。读取FAT磁盘文件,必须首先找到这个目录项,获得文件大小、创建时间、文件首簇号即文件实际数据的起始位置等信息,当需要读取数据时,再根据文件的首簇号,查找FAT表中的簇链一一读取。以下所述文件如未加说明,均为FAT磁盘文件。
根据FAT规范,一个文件的目录项位置信息最少需要如下信息:
1)该文件目录项所在磁盘分区的扇区信息
因FAT32格式最大支持32GB(GB为2的19次方字节数量)大小的磁盘分区,一个扇区占512字节(Byte),因此表示一个扇区号最多使用26比特(bit)表示。
2)该文件目录项在当前扇区中的偏移量。
由于一个扇区大小为512字节,一个目录项大小为32字节,因此一个扇区最多16个目录项,偏移量只需4bit表示。
3)该文件所在目录的目录项首簇号,占32bit。
如果不要求在显示时获取文件全路径名,则该信息不是必须的。
因此,记录一个文件的目录项位置信息,最少需要26bit+4bit+32bit=8Byte,可用C语言表示成如下数据结构:
搜索完一个磁盘分区上的所有文件后,将文件出现的顺序号作为索引号,通常以非负整数从0开始表示,每个文件的索引号唯一。具有索引号的文件称为索引文件。打开索引文件的参数为索引号和磁盘分区号,而不是文件路径,并仅以只读方式打开。所谓一个索引文件的全位置信息,是指除了索引文件的目录项位置信息外,还包含下列信息:
a)文件目录项在其所在目录的目录项中的位置偏移,以字节表示,是32的整数倍;
b)索引文件所在目录的簇号;
c)索引文件所在目录的深度。
在很多应用中,对FAT***上打开的目录深度有限制,根目录深度为0,进入一级子目录,则深度加1,二级子目录则深度为2,并依此类推。最大搜索目录深度需在搜索前固定。
d)关于索引文件所在目录的其他信息。
索引文件的全位置信息,表示了该索引文件在磁盘分区上某个目录下的相对位置。若已知索引文件A的全位置信息,才能根据索引文件A的索引号,知道另一索引号的索引文件B是在索引文件A之前还是之后,以便可以找到其他同类型文件的目录项位置信息。文件属于相同类型是指文件具有相同的格式,可以通过文件的后缀名识别出文件的类型,文件的后缀名如“.jpg”、“.mp3”、“.avi”等。
本实施例中,索引文件的全位置信息可以表示成一个包含了文件的目录项位置信息结构Diritem_AddrInfo变量的一个数据结构。
全分区搜索和部分搜索
所谓全分区搜索,是指从格式化为FAT格式的磁盘某个分区的根目录开始,根据目录结构,按照事先设定的最大目录深度,一次性搜索完该磁盘分区上的一种、几种或者所有文件类型的搜索方式。如果磁盘分区上的文件没有改变,则不必重新搜索。
所谓部分搜索,是指在当前全盘分区搜索的文件中,以与全盘分区搜索同样规定的文件类型,以某个索引文件的全位置信息为起点,在同一磁盘分区上搜索其他索引文件的方式。
本发明方案读取文件的原理为:如果一个磁盘分区上文件数量很大,为所有的文件保存它们的目录项位置信息会占用过多的内存空间,则根据事先设定的内存空间,保存一部分文件的目录项位置信息;如果需要读取其他的文件,则根据所保存的目录项位置信息通过执行部分搜索的方式来实现。
假设磁盘D上有10000个同类型文件,需要在浏览时快速打开,分配适当大小的内存空间来保存文件目录项位置信息,比如,设置能保存64个文件目录项位置信息的内存空间,共64×8=512字节,数组kFIndex[N]用于保存文件目录项位置信息,N表示所保存的目录项位置信息的数目。实际应用中,N的大小可以根据实际内存需求、以及***的运行速度进行调整。
本发明提出读取FAT磁盘文件的方法的基本流程如图1所示,包括如下步骤:
步骤101:预先对FAT格式的磁盘分区中特定类型的文件进行全分区搜索,为每一个搜索到的文件分配唯一的索引号;在内存中设置用于保存N个索引号连续的文件目录项位置信息的N维数组;
步骤102:判断所要读取的文件索引号是否在所述数组内,若是,则直接从数组内获取文件目录项位置信息;否则,确定搜索方向并将索引号i及其附近的共N个文件目录项位置信息保存到数组内,并从数组中获取目录项位置信息;
步骤103:根据所述目录项位置信息读取文件。
在首次执行全盘分区搜索的过程中,相当于为所有文件建立了一个一一对应的索引号,对10000个文件来说,其索引号分别从0到9999,而数组kFIndex[N]则只记录了索引号为0~63这64个索引文件的目录项位置信息。在整个搜索过程中,还记下了四个全位置信息,它们是在执行全盘分区搜索或部分搜索时得到的,分别是:
(1)、磁盘分区搜索到的第1个文件的全位置信息,记为Dstart
在本实施例中,Dstart是索引号为0的文件的全位置信息,一次全盘分区搜索完成后,其值不改变。其对应索引号记为Dstart_index,本实施例中,Dstart_index的值恒为0。
(2)、磁盘分区搜索到的最后1个文件的全位置信息,记为Dend。
在本实施例中,Dend是索引号为9999的文件的全位置信息,一次全盘分区搜索完成后,其值不改变。其对应索引号加上1后的值记为Dend_index,本实施例中,Dend_index的值恒为10000。
(3)、kFIndex数组中所记录的索引号最小的索引文件全位置信息,记为Mstart。
在本实施例中,Mstart为当前时刻kFIndex[0]所表示的索引文件的全位置信息,在执行部分搜索后会更新。其对应索引号记为Mstart_index,初始取为与Dstart_index相同。
(4)、kIndex数组所记录的索引号最大的索引文件的全位置信息。记为Mend。
在本实施例中,Mend为当前时刻kFIndex[63]所表示的索引文件的全位置信息,在执行部分搜索后会更新。其对应索引号加上1后的值记为Mend_index。
图2示出了执行全盘分区搜索后,kFIndex所保存的索引文件的目录项位置信息。如图2所示,在为建立索引而执行全盘分区磁盘的过程中,将保存第一个文件的全位置信息Dstart和索引号Dstart_index,以及最后一个文件的全位置信息Dend和索引号Dend_index-1;同时,还根据设定的N值,在数组kFIndex中记录下了索引号为Mstart_index到Mend_index-1这N个文件的目录项位置信息,以及索引号为Mstart_index和Mend_index-1这两个索引文件的全位置信息。其中,Mstart_index+N=Mend_index。特殊情况下,如果N>=Dend_index,则以后不必进行部分搜索。
本发明实施例提出一种读取FAT磁盘文件的方法流程如图8所示,包括如下步骤:
步骤801:预先对FAT格式的磁盘分区中特定类型的文件进行全分区搜索,为每一个搜索到的文件分配唯一的索引号;
步骤802:在内存中设置N维的数组kFIndex[N],用于保存N个索引号连续的文件目录项位置信息;在内存中保存最小索引号的文件全位置信息Dstart及对应的索引号Dstart_index、最大索引号的文件全位置信息Dend及对应的索引号Dend_index-1,数组kFIndex[N]中最大索引号的文件全位置信息Mend及对应的索引号Mend_index-1,以及数组kFIndex[N]中最小索引号的文件全位置信息Mstart及对应的索引号Mstart_index;所述文件全位置信息包括文件目录项位置信息、文件目录项在其所在目录的目录项中的位置偏移以及文件所在目录的簇号;
步骤803:判断所要读取的文件的索引号i是否在索引号Mstart_index到索引号Mend_index-1的范围内,若是,执行步骤804,否则转至步骤805;
步骤804:从数组kFIndex[N]中找到索引号i对应的文件目录项位置信息,并根据所找到的文件目录项位置信息读取所述磁盘分区上的文件,流程结束。
步骤805:在Dstart_index、Dend_index、Mstart_index和Mend_index这四个索引号之间取与i的差值最小的索引号,计为k,并以索引号k对应的文件的全位置信息为起点确定搜索方向;
步骤806:以索引号k为起点,以所确定的搜索方向进行部分搜索,将索引号i及其附近共N个文件的目录项位置信息保存到数组kFIndex[N]中,并根据数组kFIndex[N]中索引号i的文件的目录项位置信息读取所述磁盘分区上的文件。
下面再以一种具体的实施情况为例,给出详细的处理流程。假定在运行一段时间后,各个记录点的位置如图3所示,当前kFIndex保存了索引号为Mstart_index1到Mend_index1-1这N个索引文件的目录项位置信息,而且执行全盘分区搜索后,又执行过部分搜索,导致Mstartindex1不再与Dstart_index相等。读取文件的流程如图9所示,包括如下步骤:
步骤100:判断所要读取的文件的索引号i是否在索引号Mstart_index到索引号Mend_index-1的范围内,若是,则从数组kFIndex[N]中找到索引号i对应的文件目录项位置信息,并根据所找到的文件目录项位置信息读取所述磁盘分区上的文件;否则执行步骤200;
步骤200:在Dstart_index、Dend_index、Mstart_index1和Mend_index1这四个索引号之间,取与i的差值最小的索引号,计为k,并以k对应的索引文件的全位置信息为起点确定搜索方向。
确定索引方向的步骤可以为:比较i与k的大小,当i<k时向全分区搜索的相反方向执行部分搜索(记为backward),否则向全分区搜索的相同方向执行部分搜索(记为forward)。全分区搜索的方向指按照文件在存储介质上原有的从前到后的存放顺序。
步骤300:以索引号k为起点,以所确定的搜索方向进行部分搜索,将索引号i及其附近共N个文件的目录项位置信息保存到kFIndex中,并根据数组kFIndex[N]中索引号i的文件的目录项位置信息读取所述磁盘分区上的文件。
具体地,可以取kFIndex[i%N]来读取索引号i的文件的目录项位置信息。其中,i%N表示i除以N所得的余数。较佳地,保存的目录项位置信息对应的索引号范围可以是从i到i+N-1;也可以是索引号从i-(N/2)到i+(N/2)-1。
步骤400:判断kFIndex[N]保存的目录项位置信息对应的索引号是否超出允许范围,若是,则将其调整为允许范围以内。允许范围就是[Dstart_index,Dend_index-1]区间。
假设保存到kFIndex[N]的最小索引号为M,则当M<Dstart_index时,表示理论计算的、欲保存到kFIndex的最小索引值超出了左边缘,将M值调整为Dstart_index,以Dstart全位置信息forward搜索,如图4所示。同理,若需记录到kFIndex的最大索引值为N,当N>Dend_index时,表示理论计算的、欲保存到kFIndex的最大索引值超出了右边缘,N值调整为Dend_index,以Dend全位置信息backward搜索,如图5所示。但无论如何调整,所要保存的目录项位置信息个数始终为N。
步骤500:部分搜索完成后,Mstart_index1和Mend_index1需要分别更新为Mstart_index2和Mend_index2,Mstart_index2的值为M,Mend_index2的值为N,Mstart更新为索引号M对应的索引文件的全位置信息,将Mend更新为索引号N对应的索引文件的全位置信息。图6所示为重新执行部分搜索后,kFIndex所保存的目录项位置信息对应的索引号范围。其中部分搜索之前的kFIndex对应的索引号范围如虚线部分所示,部分搜索之后更新的kFIndex对应的索引号范围如粗实线部分所示。
在某些情况下,部分搜索前后的kFIndex对应的索引号范围有可能出现一部分重叠,如图7所示。部分搜索之前的kFIndex对应的索引号范围与欲更新的索引号范围在阴影区域重合,则阴影区域对应的目录项位置信息是不必更新的,此时以全位置信息Mend为起点,搜索(也是跳过)共(Mend_index2-Mstart_index1)后,更新全位置信息Mend和Mend_index,搜索完N个文件后,将后面搜索的文件的目录项位置信息保存在kFIndex中,保存个数小于N。此处所谓的搜索是指在已有的保存数据中查找是否有需要保留的内容,因为原kFIndex已经保存有阴影区域部分索引文件的目录项位置信息,这部分不必重新保存。在搜索完最后一个index文件后,更新全位置信息Mstart和Mstart_index的值。
相比而言,如果以backward方向搜索,则其起点索引号值(只可能是Mstart或者Mend)需事先减1,仍以全分区搜索有10000个索引文件为例,当前kFIndex保存了从500到564(不包含564这个索引号本身)共64个索引文件的目录项位置信息。此时,若欲打开的索引文件号i为480,则起点索引号首先减1变为563,这是当前kFIndex中对应的实际最大索引号,并取该点的全位置信息开始backword搜索。其中索引号500~512的目录项位置信息为需要保留的内容,索引号512~563的目录项位置信息为此次丢弃的内容。由于新的目标索引范围左边是480-64/2=448,右边480+64/2=512,最大索引号值为511,因此在忽略了563-511=52个索引文件后,将搜索到的第53个文件所在的全位置信息,更新到Mend;在搜索到第64个文件后,从第65个文件开始将其目录项位置信息记录到kFIndex[i%64]中,共更新64+500-512=52个文件的目录项位置信息,其余12个文件(索引号从500到511)的目录项位置信息仍留在kFIndex中。
较佳地,N的取值为2的正整数幂次。设N=2n此时在通过索引号i存取kFIndex变量元素时,可以通过kFIndex[i&((1<<n)-1)],获得比kFIndex[i%N]更高的效率。其中i表示索引号,n表示N的取值是2的几次幂,整个表达式等效于对i求N的余数。
本发明实施例还提出一种读取FAT磁盘文件的装置,包括:全分区搜索模块、存储模块、读取模块和部分搜索模块;
全分区搜索模块,用于对FAT格式的磁盘分区中特定类型的文件进行全分区搜索,为每一个搜索到的文件分配唯一的索引号;
存储模块,包括N维的序列存储单元,所述序列存储单元用于保存所述全分区搜索模块搜索到的N个索引号连续的文件目录项位置信息;根据来自部分搜索模块的索引号i及其附近共N个文件的目录项位置信息,对所保存的文件目录项信息进行更新;
读取模块,用于判断所要读取的文件索引号是否在所述存储模块的序列存储单元内,若是,则直接从序列存储单元获取文件目录项位置信息;否则,确定搜索起点以及搜索方向并向部分搜索模块发送搜索指令;待存储模块存储的内容更新后,从序列存储单元中找到索引号i对应的文件目录项位置信息,并根据所找到的文件目录项位置信息读取所述磁盘分区上的文件;
部分搜索模块用于以来自读取模块的搜索起点为起点,以读取模块所确定的搜索方向进行部分搜索,将搜索到的索引号i及其附近共N个文件的目录项位置信息发送至存储模块。
较佳地,所述存储模块还保存全分区最小索引号及该索引号对应文件的全位置信息;全分区最大索引号及该索引号对应文件的文件全位置信息;序列元素对应的最大索引号及该索引号对应文件的文件全位置信息;以及序列元素对应的最小索引号及该索引号对应文件的文件全位置信息;所述文件全位置信息包括文件目录项位置信息、文件目录项在其所在目录的目录项中的位置偏移以及文件所在目录的簇号;
所述读取模块,用于判断所要读取的文件的索引号i是否在存储模块保存序列元素对应的最小索引号到序列元素对应的最大索引号的范围内,若是,则从序列元素中找到索引号i对应的文件目录项位置信息,并根据所找到的文件目录项位置信息读取所述磁盘分区上的文件;否则,在全分区最小索引号、全分区最大索引号、序列元素对应的最大索引号和序列元素对应的最小索引号这四个索引号之间取与i的差值最小的索引号,计为k,并以索引号k对应的文件的全位置信息为起点确定搜索方向,将索引号k与所确定的索引方向发送至部分搜索模块;待存储模块存储的内容更新后,从序列存储单元中找到索引号i对应的文件目录项位置信息,并根据所找到的文件目录项位置信息读取所述磁盘分区上的文件。
所述读取模块进一步包括:
搜索方向确定单元,用于比较所述索引号k和i的大小,当i<k时,确定搜索方向为全分区搜索的相反方向,否则确定搜索方向为全分区搜索的相同方向。
所述装置进一步包括:
边界调整模块,用于判断部分搜索模块所搜索到的N个索引号中的最小索引号M1是否小于存储模块中已保存的序列元素对应的最小索引号,若是,则通知所述部分搜索模块以存储模块中已保存的全分区最小索引号对应文件的全位置信息为起点;
或者,用于判断部分搜索模块所搜索到的N个索引号中的最大索引号M2是否大于存储模块中已保存的序列元素对应的最大索引号,若是,则通知所述部分搜索模块以存储模块中已保存的全分区最大索引号对应文件的全位置信息为起点。
由于全分区搜索产生的文件目录项信息的数目太大,本发明方案通过设定一定大小的内存空间来存储一小段连续的索引号及文件目录项位置信息,在此基础上通过部分搜索的方式找到目标文件的文件目录项位置信息。内存空间大小可以根据实际内存需求以及***的运行速度调整。该方案特别适用于内存受限的嵌入式***中,可以为非目录的方式快速打开大量文件时,提供一种灵活的搜索方法。在一个实现了常规FAT文件***接口的***中,增加本发明方案提供的文件打开方式,能保持与旧有其他文件***接口的兼容,也就是说,以这种方式打开的文件,能够像以文件名打开文件后一样,使用原来的read,write等接口。
本发明方案尤其适用于数码相框、数码伴侣或数码相机中,在LCD屏中显示多幅JPEG缩略图中,能够快速前后浏览图片,也可以浏览指定索引号的文件即图片,对于存储在目录层次多的文件打开操作中,能获得优良的效果。
以上所述仅为本发明的较佳实施例而已,并不用以限制本发明,凡在本发明的精神和原则之内所作的任何修改、等同替换和改进等,均应包含在本发明的保护范围之内。