这几天放假,有点空,就拿来研究了一下,看了一会儿就开始犯晕,云里雾里的,再结合到How_to_retrieve_text_from_a_binary_doc_file这篇文章,总算知道怎么从MS Word Binary Format中提取出文字了。下面将演示用PHP从.DOC文档中提取文字。
至于用处,不用我多说,搜索引擎能索引Word、QQ邮箱可以直接以HTML方式查看Word文档,etc…
首先,找个测试文档吧,以这个aaa.doc为例。
然后要说明的是,MS Word Binary File Format版本从97到2003没太大变化,对于我们提取文本无影响,这之间的格式都遵循着OLE规范的,不懂的可以看看MS的OLE规范。
用WinHex打开这个测试文章:
选中的区域(0×30)即为文档目录的入口,0×1C出开始的两个字节FE FF表明文档使用Little Endian,即高位在后低位在前,所以这里目录的开头为0×00000041 =
65。这个65是Sector ID。
什么是Sector?Sector是将文件按512字节进行划分,第一个512直接为Header,即文件头,第二个512为Sector #0,后面的类推。
所以,要定位到目录位置,偏移算法为 (65+1)x512=33792=0×8400,定位到文件0×8400位置:
order cialis
t=”hex01″ width=”705″ height=”288″ />
本来可以按照相连的规律来读出所有的目录,但略显复杂,我们就直接判断每128个字节为一个目录,直到遇到开始两个字节为零时终止。
因为我们这里只是提取文字,所以只需要读取目录的名字(前64字节)和目录的入口(倒数第12个字节开头的4个字节),这里我们只说有用信息:
WordDocument目录位置 0×000000,即Sector #0
1Table位置 0×00001D,即Sector #29
定位到WordDocument目录位置(0+1)*0×200=0×200,偏移到0×3A0位置,可以找到Piece Table在1Table中的偏移位置:
这里为 0×2094 , 长度为0×0021
定位到Piece Table,0×2094+(0×1D+1)*0×200=0×5C94:
截取0×21个字节的长度,即为选中部分,02表示这行数据是Piece Table(PT),1C 00 00 00表示数据长度=28,可以计算出PT的数量=(28-4)/12=2,那么,00 00 00 00表示第一个PT的位置偏移,E4 05 00 00表示第一个PT的结束同时也是第二个PT的开始,BF 0B 00 00为第二个PT的结束。80 00 00 08 00 00 00 00表示第一个PT的描述,80 00 00 18 00 00 00 00表示第二个PT的描述,从描述中可以确定文本编码是Unicode双字节还是CP,还能确定字符开始的起始基数。具体算法见后面源代码。这里得到的信息是,以Unicode编码存储,起始偏移为0×800。那么文字读取的位置即为0×0800+(0×00+0×0001)*0×0200+0×0000=0xA000。然后按照Unicode编码和Little Endian顺序,就可以一个一个的将文字读取出来了。
zp8497586rq