文本文件数据压缩的无损变换 本发明涉及计算机领域文本文件的一种压缩方法,特别是文本文件数据压缩的无损变换。
人类社会已进入了信息时代,对于浩如烟海的数据必须进行有效的压缩,才能减少数据的存储容量,节约数据传输时间,提高人类资源利用率,获得更大的经济效益。经过科技工作者几十年的不懈努力,数据压缩的理论和方法不断成熟和完善,有效实用的压缩方法不断产生。1952年霍夫曼(D.A.Huffman)给出了最优变长码的构造方法,由此方法编写的软件已广泛应用于数据通讯,计算机文件压缩等。1976年,里斯桑内(J.Rissanen)给出了算术编码(Arithemtic Coding)。1977年到1978年,J acob Ziv和Abraham Lempel在IEEE Transaction on Information Theory上发表了论文:《顺序数据压缩的一个通用方法》(AUniversal Alogrithem for Seqential DataCompression),及续篇《通过可变换比率编码的独立顺序的压缩》(Copression of Individual viaVariable--Rato Coding),开创了基于字典压缩的先河。在这些数据压缩理论地指导下,人们先后编写了许多实用的压缩软件,如arj.exe,pkzip.exe,lzss.exe,arith.exe等。尽管以上方法是非常有效和实用的,但其压缩并未达到理论上的极限,而且也没有利用中文文本的特点,此外,目前计算机上常用的中西文编辑软件(如:WPS,EDIT)等都没有实时压缩功能,常常是在需传输时或永久保存时才压缩,实际上多占了存贮空间。
本发明的目的是,利用中文文本文件的特点,提出一种文本文件数据压缩的W-变换,它可有效地对中文文本文件实施压缩,进一步提高中西文文本文件的压缩比。
本发明的目的是这样实现的,
文本文件数据压缩的W-变换是一个基于字典的变换。众所周知,国标汉字库(GB2312-80)是用16位来对汉字编码的,这种编码只是为兼顾中西文而设计的,其冗余空间是很大的。由于汉字文本的特点,往往不是单个汉字出现,而是前后关联的,为利用这种前后关联性,本发明人选择了汉字文本中最常用双字词为一字典,每个双字词用16位来编码,因此只要文本中出现双字词,W-变换后对此就有压缩。
其具体实现方法如下,
1).对于源码为ASCII码的,其源码高位置1,
2).对于源码为换行符即其ASCII码为0D,0A的,将其变换后,置为0x81H,
3).对于汉字“的”,变换后将其置为0x82H,
4).对于不能组成中文词组的单字和图形符号, 将其划分为页,每页256个汉字,对其变换后,其编码第一字节:是页码+1,编码第二字节:该页在汉字库中的偏移地址,
5).对于能组成中文词组的双字词组,是将词组划分为页,每页256个词组,变换后的编码第一字节是页码+4)中所述的单字划分为页后所占的总页码,编码第二字节是其在汉字库中的偏移地址。
本发明的积极效果如下,
这种编码方法,对ASCII码来说,实际上只用了7位,高位1是解码时的标志;对汉字符号或双字词,由于最大页码小于127,实际上只用了17位编码,第16位上的“0”也是一个解码时的标致。这样解码时先读一个字节,高位是1,输出ASCII码,或换行符,或汉字“的”;如果高位是0,读下一字节,页码小于40,输出单字或符号,否则输出双字。可见,解码程序速度非常快。
以下结合实施例对本发明作进一步说明,
其变换方法见下表, 源 码 变 换 码 ASCII码 源码高位置1 换行(0D,0a) 0x81H 汉字:"的" 0x82H 不在字典中的单字 或图形号所有汉字及图形符号用40页字典编码,每页256个汉字:编码第一字节:页码+1编码第二字节:该页偏移地址(注:此时不需要查字典,计算公式如下:X=(区码-1)*94+位码-1页码=X/256+1偏移=X mod 256) 字典中双字词字典中12563个双字词分成50页每页256个词:编码第一字节:页码+40编码第二字节:偏移地址
发明人应用Turbo C 2.01为本发明编制的文本文件数据压缩的W-变换程序如下,
编码程序
-->exit(0); } if((pt2=malloc(25126))!=NULL) inittab2(pt2,fp3); else {printf("memery alloc error!");exit(0);} flag=0;while((c=getc(fp1))!=EOF){ ch[flag]=(char)c; flag=flag+1; if(flag==4){ flag=outputword(fp2,ch); i++; if(i==255){printf(".");i=0;} } } if(flag>0)fputc(0x80,fp2); switch(flag){ case 0:break; case 1: fputc(ch[0],fp2); break; case 2: fputc(ch[0],fp2) fputc(ch[1],fp2) break; case 3: fputc(ch[0],fp2) fputc(ch[1],fp2) fputc(ch[2],fp2) break; } fclose(fp1); fclose(fp2); fclose(fp3); free(pt1); free(pt2); return(0); } void inittab1(char *p,FILE *fp3) { char ch[3]; int i; int ct; int of=0; int tof; for (i=0;i<20304;i++) p[i]=0; i=0; while(i<2467) { fread (ch,3,1,fp3); i++; tof=of; of=of+(int)ch[2]; ct=(int)(ch[0]-160-16)*94+(int)(ch[1]-160-1); ct=ct*3; pt1[ct]=ch[2]; pt1[ct+1]=(char)(tof/256); pt1[ct+2]=(char)(tof%256); } }void inittab2(char *pt2,FILE *fp3) { char ch [2]; int i=0; fseek(fp3,7402L,0); while(fread(ch,2,1,fp3)>0) { pt2[i]=ch[0]; i++; pt2[i]=ch[1]; i++; } }int outputword(FILE *fp2,char *ch) int flag; unsigned int p; unsigned int length,dist; int i; unsigned int offset; unsigned int bm; if((ch[0]==0x0d)&&(ch[1]==0x0a)) { fputc (0x81,fp2); ch[0]=ch[2]; ch[1]=ch[3]; return(2); } if(ch[0]<0xa0) { fputc((ch[0]|0x80),fp2); ch[0]=ch[1]; ch[1]=ch[2]; ch[2]=ch[3]; return(3);} if(((ch[0]-0xa0)<16)||((ch[0]-0xa0)>78)) { bm=(ch[0]-0xa0-1)*94+(ch[1]-0xa0-1 fputc((char)(bm/256+1),fp2); fputc((char)(bm%256),fp2); ch[0]=ch[2]; ch[1]=ch[3]; return(2); } if((ch[0]==181)&&(ch[1]==196)) { fputc(0x82,fp2); ch[0]=ch[2]; ch[1]=ch[3]; return(2); }p=(unsigned int)(ch[0]-0xa0-16)*94+(unsigned int)(ch[1]-0xa0-1)p=p*3;length=(unsigned int)(pt1[p+1]) *256+(char)pt1[p+2];dist=pt1[p];if(dist>0) { length=(length)*2; dist=dist*2; i=0;while((i<dist)&&(pt2[length+i]!=ch[2])||(pt2[length+i-1]!=ch[3])) i=i+2; if(i<dist) { offset=(length+1+i)/2; fputc((char)(offset/256+40),fp2); fputc((char)(offset%256),fp2); return(0);} } bm=(ch[0]-0xa0-1)*94+(ch[1]-0xa0-1); fputc((char)(bm/256+1),fp2); fputc((char)(bm%256),fp2); ch[0]=ch[2]; ch[1]=ch[3]; return(2); }]]>
程序说明:
(1).编码(W-变换):
程序中用到了一个数据文件(Wordtab.bin),长度为32528字节,其结构如下:
第一部分:共7402字节。(即2467*3+1),每三个字节为一变量:第一、二字节为汉字内码,所选汉字为所有双字词的第一个字(不重复,共2467个),第三字节为该汉字所组成的词组个数;最后一个字节为一分隔符(0xFFH)。
第二部分:共25126个字节。依次存储双字词字典中第二个汉字的内码。
指针pt1指向第一个缓存区,长度为72*94*3=20304字节,即从16区到87区的汉字每字分配三个字节的单元,如果该字属于双字词的第一字,则这三个字节的第一个字节置该字能组成双字词的个数(dist),第二、三字节为16位无符号整数,存储该字组成双字词的第二个字在pt2中的偏移地址(length);否则,三个字节全为0°指针pt2指向第二个内存区,长度为12563*2=15126字节,依次存放双字词的第二个字。
应用pt1和pt2的目的是要加快查找速度:当输入文件读到一个汉字后,由内码计算出它在pt1中的偏移地址p,如果pt1[p]等于0,则该字不组成词组,直接按编码方法输出;否则,该字可能组成词组,再读第二个汉字,用第二个汉字与pt2[length]到pt2[length+dist]之间的串进行比较,如果查到,输出词组编码,否则输出第一个字,返回。可见,由于dist平均长度为5,这就大大缩短了查找速度,提高了程序运行速度。
应用本程序对文本文件压缩后的实验结果:
这里选择了5个文本文件作为实验例文。其中shy1.txt是W-变换的双字词字典文件,其压缩效果最好,比arj.exe提高了20%左右。shy.txt是一个中英文及表格混排文件。其它三个文件分别为新闻,股评或论文等。比较结果如下表。
(见下页)
W-变换与Huff1,Arj,Pkzip之比较 实 验 文件名 及长度 (字节) W-变换 后象文 件 长 (字节) 与Huff编码比较 与ARJ比较 与Pkzip比较 W-变换 +Huff1 Huff1 W-变换 +Arj Arj W-变换 +Pkzip Pkzip shy1 75379 37740 28678 61% 52490 30.7% 26441 64.9% 41714 44.6% 26817 64.4% 41450 45.0% shy2 80824 80824 45686 43.4% 54931 32.0% 22218 72.5% 23864 70.4% 21971 72.8% 23565 70.8% shy3 46817 37434 32583 30.4% 37529 19.8% 21600 53.8% 23391 50.0% 21519 54.0% 23157 50.5% shy4 29756 20888 18760 36.9% 23783 20.0% 14739 50.3% 16192 45.5% 14676 50.7% 16220 45.5% shy5 28361 18336 16426 42.1% 22500 20.7% 6711 76.3% 7821 72.4% 6704 76.4% 7812 72.4%
注:表中所用百分比为:
(源文件长-压缩后文件长)/源文件长*100/100