哈夫曼文件压缩源文件+头文件

来源:互联网 发布:c语言结构体 编辑:程序博客网 时间:2024/05/02 02:01
#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;
}
charfind(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<0perror(" 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<0perror(" 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)<0perror("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)<0perror("writecode error!");
                if(write(fd2,&t,1)<0perror("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<0perror(" 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<0perror(" 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<0perror(" 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))<0perror("write.. error!"); 
    }
}
void uncompressing(char* name)
{
    struct _filestate *f = malloc(sizeof(struct _filestate));
    int r;
    int fdr = open(name,O_RDONLY);
    if(fdr<0perror("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<0perror("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;
}
0 0
原创粉丝点击