#ifndef
_YASUO_
#define
_YASUO_
int count;
//临时变量
/结构体1:字符的出现次数
struct
_symbol{
char character;
unsigned
int number;
};
//struct _symbol symbol_list[128];
/结构体2:文件的状态记录
struct
_filestate{
char symbol_count;
struct
_symbol symbol_list[
128];
};
/结构体3:哈夫曼树的结点
struct
_node{
unsigned
int temp;
struct
_symbol* symbol;
struct
_node* left;
struct
_node* right;
};
typedef
struct
_node _node;
/结构体4:字符的编码字典项
struct
_dictionary_itme{
struct
_symbol* symbol;
char coding[
20];
};
/结构体5:字符的编码字典
struct
_dictionary{
int count;
struct
_dictionary_itme itme[
128];
};
void
init();
//初始化
void
compressing(
char*);
//压缩
void
uncompressing();
//解压
void
read_file(
char*);
//读取文件
_node*
creat_haffman();
//创建哈夫曼树
_node*
creat_node(
struct
_symbol*);
//创建节点
void
creat_dictionary(_node*);
//创建压缩字典
void
coding_file(
char*);
//编码
void
creat_haffman_coding(
char*,_node*);
//创建哈夫曼编码
#endif
//==============================================
#include
<stdio.h>
#include
<stdlib.h>
#include
<fcntl.h>
#include
<sys/stat.h>
#include
<string.h>
#include
"yasuo.h"
//变量区
int i =
0;
char* head =
NULL;
struct _filestate filestate;
//结构体2:文件的状态记录
_node** node_list;
_node* root;
struct _dictionary dictionary;
//结构体5:字符的编码字典
void
init()
{
int i;
count=
0;
bzero(&filestate,sizeof(filestate));
bzero(&dictionary,sizeof(dictionary));
}
void
creat_haffman_coding(
char* coding,_node* _root)
{
if(_root->
left==
NULL&&_root->
right==
NULL)
{
strcpy(dictionary.
itme[i].
coding,head);
dictionary.
itme[i].
symbol = _root->
symbol;
//printf("%d.%s %c %d\n",i,dictionary.itme[i].coding,dictionary.itme[i].symbol->character,dictionary.itme[i].symbol->number);
i++;
return;
}
if(_root->
left!=
NULL)
{
*coding=
'0';
creat_haffman_coding(coding+
1,_root->
left);
*coding =
0;
}
if(_root->
left!=
NULL)
{
*coding=
'1';
creat_haffman_coding(coding+
1,_root->
right);
*coding =
0;
return;
}
}
int g=
0;
void
bianli(_node* node)
{
if(node ==
NULL)
return;
bianli(node->
left);
printf(
"%d.%d\n",g++,node->
temp);
bianli(node->
right);
}
void
creat_dictionary(_node* _root)
{
int i;
dictionary.
count = filestate.
symbol_count;
char coding[
20] = {
0};
head = coding;
//printf("%d \n",dictionary.count);
creat_haffman_coding(coding,_root);
return;
}
char*
find(
char ch)
{
int i =
0;
while(i<dictionary.
count)
if(ch==dictionary.
itme[i].
symbol->
character)
return dictionary.
itme[i].
coding;
else i++;
return
NULL;
}
void
coding_file(
char* filename)
//将源文件转化为哈弗曼编码
{
int fd =
open(filename,O_RDONLY);
if(fd<
0)
perror(
" open error!");
char filename2[
20] = {
0};
sprintf(filename2,
"%s.vvei",filename);
//printf("%s\n",filename2);
int fd2 =
open(filename2,O_CREAT|O_RDWR);
if(fd2<
0)
perror(
" open2 error!");
unsigned
char temp =
0;
printf(
"1.%d\n",sizeof(filestate));
int r;
r =
write(fd2,&filestate,sizeof(filestate));
if(r<
0)
perror(
" write error!");
printf(
"3.%d\n",r);
// struct _filestate f;
// r = read(fd2,&f,sizeof(f));
// if(r<0)perror("read error!");
// printf("4.%d\n",r);
// printf("%d %d\n",f.symbol_count,filestate.symbol_count);
unsigned
char ch =
0;
unsigned
char ch1 =
0;
char* code =
"\0";
int flag =
0;
printf(
"%d\n",*code);
int gg=
55;
while(
1)
//将读到的字符转成哈夫曼编码再写到压缩文件中去
{
if(flag>
7)
{
if(
write(fd2,&ch1,
1)<
0)
perror(
"writecode error!");
//printf("%d\n%s\n",ch1,code);
flag =
0;
ch1 =
0;
//break;
}
if(*code==
'0')
{
ch1*=
2;
code+=
1;
flag++;
}
else
if(*code==
'1')
{
ch1*=
2;
ch1++;
code+=
1;
flag++;
}
else
if(*code==
0)
{
if(
read(fd,&ch,
1))
{
code =
find(ch);
//printf("%c %s\n",ch,code);
}
else
{
char t = flag%
8;
ch1*=t;
if(
write(fd2,&ch1,
1)<
0)
perror(
"writecode error!");
if(
write(fd2,&t,
1)<
0)
perror(
"writecode error!");
break;
}
}
else
perror(
"code error!");
}
}
void
read_file(
char* filename)
{
int i =
0;
int result =
0;
unsigned
char ch=
0;
// FILE *f = fopen(filename,"r");
// if(f==NULL){perror("fopen error!");}
int fd =
open(filename,O_RDONLY);
if(fd<
0) {
perror(
" open error");
return;}
unsigned
char symbol[
128] = {
0};
while(result =
read(fd,&ch,
1))
{
if(result<
0)
{
perror(
"readfile error!");
return;}
symbol[ch]++;
}
for(i=
0;i<
128;i++)
{
if(!symbol[i])
continue;
filestate.
symbol_list[filestate.
symbol_count].
character = i;
filestate.
symbol_list[filestate.
symbol_count++].
number = symbol[i];
//printf("%d. %d %d\n",filestate.symbol_count,filestate.symbol_list[filestate.symbol_count-1].character,filestate.symbol_list[filestate.symbol_count-1].number);
}
close(fd);
}
_node*
creat_node(
struct _symbol* s)
{
_node* p;
p =
malloc(sizeof(_node));
p->
temp = s->
number;
p->
symbol = s;
p->
left =
NULL;
p->
right =
NULL;
return p;
}
_node*
creat_haffman(
struct _filestate* filestate)
//(未用优先队列实现)
{
_node* parent =
NULL;
unsigned
char i,j;
//临时变量
node_list = (_node**)
malloc(filestate->
symbol_count*sizeof(_node*));
for(i=
0;i<filestate->
symbol_count;i++)
{
node_list[i] =
creat_node(&(filestate->
symbol_list[i]));
}
// printf("===================\n");
// for(i=0;i<filestate.symbol_count;i++)
// {
// printf("%d %d %d\n",i,node_list[i]->symbol->character,node_list[i]->temp);
// }
unsigned
char minidx =
0;
unsigned
char secidx =
0;
for(i=
0;i<filestate->
symbol_count-
1;i++)
{
j=
0;
while(!node_list[j])
{
j++;
}
minidx = j;
for(j=
0;j<filestate->
symbol_count;j++)
{
if(node_list[j]!=
NULL && node_list[j]->
temp < node_list[minidx]->
temp)
minidx = j;
}
//printf("min:%d \n",node_list[minidx]->temp);
j=
0;
while(j==minidx || !node_list[j])
{
j++;
}
secidx = j;
for(j=
0;j<filestate->
symbol_count;j++)
{
if(j!=minidx && node_list[j]!=
NULL && node_list[j]->
temp < node_list[secidx]->
temp)
secidx = j;
}
//printf("sec:%d \n",node_list[secidx]->temp);
parent =
malloc(sizeof(_node));
parent->
temp = node_list[minidx]->
temp + node_list[secidx]->
temp;
parent->
symbol =
NULL;
parent->
left = node_list[minidx];
parent->
right = node_list[secidx];
node_list[minidx] = parent;
node_list[secidx] =
NULL;
//secidx = 0;
// for(j=0;j<filestate.symbol_count;j++)
// {
// if(node_list[j]!=NULL && node_list[j]->temp>node_list[minidx]->temp)
// secidx = j;
// }
}
// int a=0;
// for(i=0;i<filestate.symbol_count;i++)
// {
// if(node_list[i]!=NULL)a++,printf("%d\n",a);
// }
return parent;
}
void
compressing(
char* filename)
{
read_file(filename);
root =
creat_haffman(&filestate);
//创建哈夫曼树
creat_dictionary(root);
coding_file(filename);
//将源文件转化为哈弗曼编码
char* s =
find(
'u');
printf(
"%c %s\n",
'u',s);
}
char
findchar(_node* p,
int fd,
unsigned
char* t,
int* f)
{
(*f)--;
if(*f<
1)
{
int r =
read(fd,t,
4);
if(r<
0)
perror(
" read error!");
else
if(r==
0)
{
return -
1;
}
*f =
8;
}
if(p->
left==
NULL&&p->
right==
NULL)
return p->
symbol->
character;
if((*t>>*f)%
2)
return
findchar(p->
right,fd,t,f);
else
return
findchar(p->
left,fd,t,f);
}
void
jieya(_node* root,
int fdr,
int fdw)
{
unsigned
char temp=
0;
char ch;
int flag=-
1;
int r;
_node* p =
NULL;
// unsigned int te=0;
// int gg=1;
// char s[34]= "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.";
// int f;
while(
1)
{
if(flag<
0)
{
r =
read(fdr,&temp,
1);
if(r<
0)
perror(
" read error!");
else
if(r==
0)
return;
flag =
7;
// te = temp;
// printf("%d..%d",gg,temp);
// f = 31;
// while(f+1)
// {
// s[f--] = (char)(te%2+48);
// te/=2;
// }
// printf(" %s\n",s);
}
// if((temp>>flag)%2)
// ch = findchar(root->right,temp,&flag);
// else ch = findchar(root->left,temp,&flag);
// ch = findchar(root,fdr,&temp,&flag);
p = root;
while(
1)
{
if(flag<
0)
{
r =
read(fdr,&temp,
1);
if(r<
0)
perror(
" read error!");
else
if(r==
0)
return;
flag =
7;
// te = temp;
// printf("%d..%d",gg,temp);
// f = 31;
// while(f+1)
// {
// s[f--] = (char)(te%2+48);
// te/=2;
// }
// printf(" %s\n",s);
}
if(p->
left==
NULL&&p->
right==
NULL)
{
ch = p->
symbol->
character;
//printf(" %c\n",ch);
break;
}
if((temp>>flag)%
2)
p = p->
right,flag--;
else p = p->
left,flag--;
}
if((
write(fdw,&ch,
1))<
0)
perror(
"write.. error!");
}
}
void
uncompressing(
char* name)
{
struct _filestate *f =
malloc(sizeof(
struct _filestate));
int r;
int fdr =
open(name,O_RDONLY);
if(fdr<
0)
perror(
"openr error!");
//读取文件头
if((
read(fdr,f,sizeof(
struct _filestate))<
0))
perror(
"read error!");
//创建哈弗曼树
_node* root =
creat_haffman(f);
char name2[
20];
int len =
strlen(name)-
5;
name[len] =
0;
sprintf(name2,
"%s.ievv",name);
printf(
"%s\n",name2);
int fdw =
open(name2,O_CREAT|O_WRONLY);
if(fdw<
0)
perror(
"openw errorint!");
//printf("%d\n",fdw);
//将读压缩文件,创建解压文件
jieya(root,fdr,fdw);
}
int
main(
int argc,
char
const *argv[])
{
init();
if(argv[
1][
0]==
'-')
if(argv[
1][
1]==
'y')
compressing((
char*)argv[
2]);
else
if(argv[
1][
1]==
'j')
uncompressing((
char*)argv[
2]);
else
printf(
"input error\n");
return
0;
}