首页 > 代码库 > 电子书格式探秘
电子书格式探秘
2. mobi格式的(仅就英文文本和未加密的文档而言)相对比较压缩比较简单,有时我们看一眼也能猜到是什么内容,mobi的文本压缩大致如下:
a. 英文:开始时一定是完整的单词(因为前面什么都没有),如果有前面出现过的内容>=3 且<=10,用2个16进制数表示:前4位一定是80--BF(X000- ),后12位表示向前索引的值和长度。其中最后3位表示长度,9位右移3位得到的数是向前索引的值。例如: This is a test.可以压缩成(This 8018a test)解释为(X000 0000 000X 0000)开头4位为8表示前面有出现过、后三位为0表示长度为0+3、最多等于(XXX)7+3、右移3位得到(000000XX),也就是说8080这个位置向前数3个字符(空格也是字符)长度为3得到is+空格。
b. 英文空格出现的频率很高,因此如果没有长度3-10的重复,空格就和后面的字符+80(16进制)合成一个字符,如:空格+He(48+80)编码为:C865,空格+he编码成:E865。F765解压为:we。
c. 中文和一些特别符号:看来mobi的压缩不适合中文,或许动态建议词典来索引,分析有难度,通常中文和特别符号用一个16进数表示:前4位一定是0(0000),后4位表示这几个字符没有压缩,如06表示:后面的6个字符没有压缩(照抄)。
以上是mobi格式压缩解压abc,实际文件还有其它图片、中文索引等内容的压缩,就没有办法分析了。
用delphi编写的解码程序如下代码:
begin //开始逐字读入压缩的mobi,假定变量和函数已定义;
counter:=0; //计数器;
j:=0; //读数器;
tm.Position:=0; //tm=TMemoryStream; 动态分配的内存且已经读入mobi文件;
while (j<size-2) do //size 为文件长度,可以根据文件索引调整起始位置;
begin
tm.Read(rd1,1); //读入一个字符;
inc(j);
fm.Seek(counter,0); // 定位指针要时而往前,时而往后,因此在读入每个字符时重新定位;
case rd1 of //简单地用一个case分别处理不同情况;
$80..$bf: //美元符号表示16进制数;仅初步判断到的可能大致分界。(压缩设计者会把所有能利用的空间想办法用足);
begin
tm.Position:=tm.Position-1;
tm.Read(bw,2);
bw:=swap(bw) and $7fff;
sm1:=CountTrace(bw)+3;
writeMem(sm1);
inc(j);
end;
$1..$0f:
for i:=0 to rd1-1 do
begin
tm.Read(rd2,1);
inc(j);
fm.Write(rd2,1);
inc(counter);
end;
$c0..$ff:
begin
c:=$20;
fm.Write(c,1);
inc(counter);
c:=rd1 and $7f;
fm.Write(c,1);
inc(counter);
end;
$0: inc(counter);
else
fm.Write(rd1,1);
inc(counter);
end;
end;
fm.Position:=0;
outstream.CopyFrom(fm,counter-1);
fm.Free;
tm.Free;
end;
以上程序在delphi7.0 编译通过。
电子书格式探秘