文件分析 ifo词典定义说明等描述文件。
1 2 3 4 5 6 7 8 9 10 11 12 version= bookname= wordcount= synwordcount= idxfilesize= idxoffsetbits= author= email= website= description= date = sametypesequence=
举例1:
.dict数据文件全部由 wav
声音文件组成声音数据文件格式。
所以,读取时可以直接忽略w类型和长度按照idx文件中的数据长度读取即可。
1 2 3 4 word_1_data word_2_data word_3_data ……
举例2:
t:音标格式
1 2 word_1_data_1_data + /0 word_1_data_2_data
m:纯文本数据格式
1 2 word_2_data_1_data + /0 word_2_data_2_data
dict/dict.dz虽然格式为dz,在Linux下使用file命令查看文件格式为gz,所以直接把后缀修改然后解压就可以了。
词典最原始的数据文件,文件结构遵从ifo文件中的定义。
数据类型没有定义的时候,遵循以下结构:
1 2 3 4 5 6 7 8 9 10 word_1_data_1_type; word_1_data_1_data; word_1_data_2_type; word_1_data_2_data; ...... word_2_data_1_type; word_2_data_1_data; ......
idx/idx.gz词条的索引文件,按升序排序。
1 2 3 word_str; word_data_offset; word_data_size;
syn同义词定义文件。2.4.8以上版本支持
1 2 synonym_word; original_word_index;
数据解析首先解析.info格式文件,获取里面的version条目,如果是3.x版本,则读取idxoffsetbits字段,如果包含此字段,那就表示字典数据长度为64位,即8字节。
首先从.idx中获取单词、偏移量、信息长度。
打开文件
1 2 3 4 5 6 7 8 9 10 11 12 QFile file ("CET6.idx" ) ;if (!file.exists ()){ qDebug ()<<"File does not exists." <<file.fileName (); return -1 ; }if (!file.open (QFile::ReadOnly)){ qDebug ()<<"File cannot open: " <<file.fileName (); return -1 ; } QByteArray ba = file.readAll (); file.close ();qDebug ()<<"idx size is: " <<ba.size ();
idx数据结构为:
1 2 3 4 长度不固定 固定4字节 固定4字节 +---------+--------+--------+ + word + offset + length + +---------+--------+--------+
单词 不同单词长度不同,但是都是以’\0’结束 偏移 此单词对应的数据在.dict中的开始位置,大端数据,固定2.x版本32位,3.x版本64位 长度 此单词在.dict中数据的长度,大端数据,固定2.x版本32位,3.x版本64位 获取单词的长度
1 2 3 4 5 6 7 int getWordSize (QByteArray ba,int index) { int i=0 ; while (ba.at (index+i)!='\0' ){ i++; } return i; }
当前操作的位置为index,单词的长度为len,那么offset的值计算方法为
1 uint32_t pos = (uchar)ba[index+len+4 ]+(ba[index+len+3 ]<<8 )+(ba[index+len+2 ]<<16 )+(ba[index+len+1 ]<<24 );
数据长度的计算方法为
1 uint32_t size = (uchar)ba[index+len+8 ]+(ba[index+len+7 ]<<8 )+(ba[index+len+6 ]<<16 )+(ba[index+len+5 ]<<24 );
这样就得到了单词、位置、长度。
将dict.dz文件解压为dict格式。然后打开文件
1 2 3 4 5 6 7 8 9 10 11 QFile filedict ("CET6.dict" ) ;if (!filedict.exists ()){ qDebug ()<<"File does not exists." <<filedict.fileName (); return -1 ; }if (!filedict.open (QFile::ReadOnly)){ qDebug ()<<"File cannot open: " <<filedict.fileName (); } QByteArray dictData = filedict.readAll (); filedict.close ();qDebug ()<<"dict size is: " <<dictData.size ();
获取对应单词的数据
此数据是UTF8格式的,可能包含中文,所以需要编码。
1 2 3 QString getCodedData (QByteArray ba) { return QString::fromUtf8 (ba); }
循环解码的步骤为
1 2 3 4 5 6 7 8 9 10 11 12 int index=0 ,len=0 ;int cnt=10 ;while (index<ba.size () && cnt--){ len=getWordSize (ba,index); uint32_t pos = (uchar)ba[index+len+4 ]+(ba[index+len+3 ]<<8 )+(ba[index+len+2 ]<<16 )+(ba[index+len+1 ]<<24 ); uint32_t size = (uchar)ba[index+len+8 ]+(ba[index+len+7 ]<<8 )+(ba[index+len+6 ]<<16 )+(ba[index+len+5 ]<<24 ); qDebug ()<<ba.mid (index,len)<<pos<<size; qDebug ()<<getCodedData (dictData.mid (pos,size)); index+= len + 9 ; }
单词长度为len,单词后面还跟着一个’\0’,位置为4字节,长度为4字节,所以固定偏移为9,完整偏移长度为index+len+9。
效果为:
第一个单词的信息长度为499,但是实际文字长度为325,那是因为汉字对个两个字节。