void Init(void) {
int i;
for (i=0;i<255;i++) {
Weight[i]=0;
WeiL[i].asc=WeiL[i].wei=0;
}
Number=0;
}
void ReadFile(char *fn) {
FILE *fp;
long int len=0;
char ch;
strcpy(Head.fn,fn);
if ((fp=fopen(fn,"rb"))==NULL) {
printf("File Not Found!");
exit(-1);
}
while(!feof(fp)) {
ch=fgetc(fp);
Weight[(int)ch]++;
len++;
}
Head.filelength=len;
fclose(fp);
}
void ConvertWeight(void) {
int i;
for (i=0;i<255;i++)
if (Weight[i]!=0) {
WeiL[Number].asc=i;
WeiL[Number].wei=Weight[i];
Weight[i]=Number;
Number++;
}
Head.number=Number;
}
void Select(HuffmanTree &HT,int n,int &s1,int &s2) {
int i;
long int wei=60000;
for (i=0;i<n;i++)
if ((HT+i)->parent==0)
if ((HT+i)->weight<wei) {
s1=i;
wei=(HT+i)->weight;
}
wei=60000;(HT+s1)->parent=1;
for (i=0;i<n;i++)
if ((HT+i)->parent==0)
if ((HT+i)->weight<wei) {
s2=i;
wei=(HT+i)->weight;
}
(HT+s1)->parent=(HT+s2)->parent=0;
}
void HuffmanCoding(HuffmanTree &HT) {
int m,i,pw,start,c,f,s1,s2;
char cd[255];
HTNode *p;
m=Number*2-1;pw=0;
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
for (p=HT,i=1;i<=Number;++i,++p,++pw) {
p->weight=WeiL[pw].wei;
p->asc=WeiL[pw].asc;
p->parent=p->lchild=p->rchild=0;
}
for (;i<=m;++i,++p) p->weight=p->parent=p->lchild=p->rchild=0;
for (i=Number+1;i<=m;++i) {
Select(HT,i-1,s1,s2);
(HT+s1)->parent=(HT+s2)->parent=i-1;
(HT+i-1)->lchild=s1;(HT+i-1)->rchild=s2;
(HT+i-1)->weight=(HT+s1)->weight+(HT+s2)->weight;
}
cd[Number-1]='\0';
for (i=0;i<Number;++i) {
start=Number-1;
for (c=i,f=(HT+i)->parent;f!=0;c=f,f=(HT+f)->parent)
if ((HT+f)->lchild==c) cd[--start]='0';
else cd[--start]='1';
strcpy(HC[i],&cd[start]);
}
}
void PackFile(char *fn) {
FILE *fpin,*fpout;
long int pp=0;
unsigned int i,num,length,count;
char ch,*buffer;
fpout=fopen(fn,"wb");
fpin=fopen(Head.fn,"rb");
buffer=(char *)malloc(255);
fwrite(&Head,sizeof(Head),1,fpout);
for (i=0;i<Number;i++)
fwrite((WeiL+i),sizeof(WeightList),1,fpout);
num=length=count=0;
while(!feof(fpin)) {
ch=fgetc(fpin);
length=strlen(HC[Weight[ch]]);
strcpy(buffer,HC[Weight[ch]]);
for (i=0;i<length;i++) {
num*=2;
if (buffer[i]=='1') num++;
count++;
if (count>=15) {
fwrite(&num,sizeof(num),1,fpout);
if (pp++%1000==0) printf(".");
count=num=0;
}
}
}
while(count<=15) { num*=2;count++; }
fwrite(&num,sizeof(num),1,fpout);
free(buffer);
fclose(fpin);
fclose(fpout);
}
void UnpackFile(char *fn) {
FILE *fin,*fout;
long int pp=0;
struct FileStruct head;
int i,j,p,seek;
unsigned int num;
long int flen,count;
char bin[17];
HuffmanTree ht;
if ((fin=fopen(fn,"rb"))==NULL) {
printf("File Not Found!");
exit(-1);
}
fread(&Head,sizeof(Head),1,fin);
fout=fopen(Head.fn,"wb");
Number=Head.number;
for (i=0;i<Number;i++)
fread((WeiL+i),sizeof(WeightList),1,fin);
HuffmanCoding(ht);
flen=Head.filelength;
seek=sizeof(Head)+Number*sizeof(WeightList);
fseek(fin,seek,0);
i=count=0;
p=2*Number-2;
while(count<flen) {
i=0;
fread(&num,sizeof(num),1,fin);
for (j=14;j>=0;j--) {
if (num%2==1) bin[j]='1';
else bin[j]='0';
num/=2;
}
bin[15]=0;
while (1) {
if (bin[i]=='0')
p=(ht+p)->lchild;
else if (bin[i]=='1')
p=(ht+p)->rchild;
i++;
if (i>15) break;
if (((ht+p)->lchild==0)&&((ht+p)->rchild==0)) {
if (count>=flen-1) {
count++;break;
}
fwrite(&(ht+p)->asc,1,1,fout);
if (pp++%1000==0) printf(".");
count++;
p=2*Number-2;
}
}
}
fclose(fin);
fclose(fout);
free(ht);
return ;
}
void main(int argc,char *argv[]) {
HuffmanTree HT;
if (argc==1) {
printf("This is The HuffmanCoding Zip Program.\n");
printf(" -----C.Chen 1999\n");
printf("Use: PACK:HUFF -h [source filename] [object filename].\n");
printf(" UNPACK:HUFF -u [source filename]. \n");
}
else if (argc==4) {
if (strcmp(argv[1],"-h")==0) {
ReadFile(argv[2]);
ConvertWeight();
HuffmanCoding(HT);
PackFile(argv[3]);
}
else printf("Use ERROR!");
}
else if (argc==3) {
if (strcmp(argv[1],"-u")==0) UnpackFile(argv[2]);
}
else
printf("Use ERROR!");
}