int main (void ) { HuffmanTree ht; HuffmanCode hc; printf ("\n\n\t\t\tWellcome!!!\n\n"); char ch ; ch = getchar (); int w[N] = {0}; //字符频度 Init (ht, w); CrtHuffmanTree (ht, w); CrtHuffmanCode (ht, hc); printf ("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); printf ("-----------------------简单文本压缩工具------------------------\n"); printf ("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); printf ("**** ****\n"); printf ("**** 1、压缩. (Local.souce -> Local.zig) ****\n"); printf ("**** ****\n"); printf ("**** 2、解压. (Local.zig -> Local.final) ****\n"); printf ("**** ****\n"); printf ("**** local.code (编码文件) ****\n"); printf ("**** ( 自行检查相应文件 ) ****\n"); printf ("**** Enter 'q' to quit ****\n"); printf ("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); printf ("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); printf ("Now your choice: "); setbuf (stdin, NULL); ch = getchar (); if (ch == '1') compress (ht, hc); else if(ch == '2') uncompress (); else if (ch == 'q') return 0; return 0; }
//压缩 void Compress(char *desFile) { MyType maxLen,minLen,ch,bits,n,finalLength; int i; short LeafNum,codeNum; WeightType count = 0,Length=0,FileLength; FILE *fp,*compressFile; SeqQueue *Q; HTNode *ht = NULL; char **hc= NULL,**Map = NULL,*p; char zip[100]; strcpy(zip, desFile); strcat(zip, ".hf"); compressFile = fopen(zip,"wb"); fp = fopen(desFile,"rb");//原文件 if(!fp || !compressFile) { puts("Cannot open file."); return ; } ht = CreatHFM(fp,&LeafNum,&FileLength);//创建哈夫曼树,统计叶子个数和原文件长度 if( !FileLength ) { // printf("文件为空,无须压缩..."); fclose(fp); fclose(compressFile); free(ht); return ; } Q = (SeqQueue *)malloc(sizeof(SeqQueue)); InitQueue(Q); hc = CrtHuffmanCode(ht,LeafNum);//取得哈夫曼0、1编码,hc的长度为LeafNum //Map为了取编码好定位,再建立全部(256个)// Map = (char **)malloc(N*sizeof(char *));//字符编码表 if(!Map) { puts("申请空间失败"); return ; } for(i = 0;i < N;i++)//初始化 Map[i] = NULL; for(i = 0;i < LeafNum;i++)// 定位,编码指针数组Map[256] Map[(int)(ht[i].ch)] = hc[i]; fseek(compressFile,sizeof(WeightType)+sizeof(short)+6*sizeof(MyType),SEEK_SET);//先占个位置 //填压缩叶子编码剩几个和最长编码长getchar(); MaxMinLength(compressFile,ht,hc,LeafNum,&maxLen,&minLen);//获得最长码串长度,顺便填写字符对应编码长 free(ht); codeNum = CodeToFile(compressFile,hc,LeafNum,Q,&finalLength);//把字符转成其二进制编码写入文件,返回压成多少个 rewind(compressFile);//使文件指针移到开始printf("ftelll = %d\n",ftell(compressFile)); fseek(compressFile,sizeof(WeightType)+sizeof(MyType),SEEK_SET); fwrite(&LeafNum,sizeof(short),1,compressFile);//写入叶子个数 fwrite(&maxLen,sizeof(MyType),1,compressFile);//最长码串长度 fwrite(&minLen,sizeof(MyType),1,compressFile);//最短码串长度 fwrite(&codeNum,sizeof(short),1,compressFile); //填写叶子编码压多少个 fwrite(&finalLength,sizeof(MyType),1,compressFile); //最后剩 fseek(compressFile,2*LeafNum*sizeof(MyType)+codeNum,SEEK_CUR); fseek(fp,0,SEEK_SET); printf("Please wait a minute,compressing..."); while(count < FileLength) { ch = fgetc(fp); ++count; for(p = Map[ch];*p != '\0';p++) In_seqQueue(Q,*p); while(Q->length > 8)// printf("OutQueue: "); { bits = GetBits(Q);//出队8个元素,合成一个字节 fputc(bits,compressFile);//fwrite(&bits,1,1,compressFile); Length++;// printf("压:%c\n",bits); } } //最后一个bits ; finalLength = Q->length;//printf("最后剩Qlength:%d\n",Q->length); n = 8 - finalLength; bits = GetBits(Q); //printf("最后Qlength:%d\n",Q->length); for(i = 0;i < n;i++) bits = bits << 1;//以‘0’补 fwrite(&bits,sizeof(MyType),1,compressFile); Length++; rewind(compressFile);//原文件长fwrite(&FileLength,sizeof(WeightType),1,compressFile); fwrite(&Length,sizeof(WeightType),1,compressFile);//压缩后的长 fwrite(&finalLength,sizeof(char),1,compressFile);//最后的串长 Length = Length + 12 + codeNum; if(Length >= FileLength) puts("\nCompression rate: 0.0%"); else printf("\nCompression rate: %.2lf%c\n",(double)((FileLength-Length)/(double)FileLength)*100.0,'%'); fclose(fp); fclose(compressFile); free(Q); free(hc); free(Map); }
//解压缩 void uncompress () { FILE *cfp, *ucfp, *message, *data; char *code ;//解压文本编码 int ch, i, j; int flag; int length = 0; //压缩文件长度 int hcount = 0; static int size = 8 * sizeof (char); char temp[N]; int count1 ;//解压文本关键字数 HuffmanTree ht; HuffmanCode hc; if ((data = fopen ("Local.data", "rb")) == NULL) { printf ("Open failed\n"); exit (0); } fread (ht, sizeof (HuffmanTree), 1, data); for (count1 = 1; ht[count1].ch ; count1++); count1--; CrtHuffmanCode (ht, hc); //解压 if ((code = (char *) malloc (MAX * sizeof (char))) == NULL) { printf ("failed!\n"); exit (0); } memset (code, 0, sizeof (code)); if ((cfp = fopen ("Local.zig", "rb")) == NULL) { printf ("Open %s failed!\n", "Local.zig"); exit (0); } if ((message = fopen ("message.f", "r")) == NULL) exit (0); fread (&flag, sizeof (int), 1, message); fread (&length, sizeof (int), 1, message); while ((ch = getc (cfp)) != EOF) { hcount++; memset (temp, 0, sizeof (temp)); for (i = size - 1; i >= 0; i--, ch >>= 1) temp[i] = (1&ch) + '0'; if (hcount == length) temp[flag] = '\0'; strcat (code, temp); } //译码 int len_cd;//最长字符编码 char cd_1[MAX] = {0, 0, 0}; char str[MAX] = {0,0,0}; int tag; //判断是否匹配成功 int len_ch = 0;//解压后文本长 int len = 0;//已译码数 len_cd = strlen (hc[1]); for (i = 2; i <= count1; i++) if (strlen (hc[i]) > len_cd) len_cd = strlen (hc[i]); while (copy (code, cd_1, len)) { for (i = len_cd; i > 0; i--) { memset (temp, 0, sizeof (temp)); //清空temp[] strncpy (temp, cd_1, i); tag = 0; for (j = 1; j <= count1 && tag == 0; j++) if (strcmp (temp, hc[j]) == 0) { str[len_ch++] = ht[j].ch; tag = 1; len += i; } if (tag == 1) break; } } if ((ucfp = fopen ("Local.final", "wb")) == NULL) { printf ("Open %s failed!\n", "Local.decode"); exit (0); } fputs (str, ucfp); fclose (ucfp); fclose (message); fclose (cfp); fclose (data); free (code); printf ("Uncompress succeed!\n"); }