一个用C实现的哈弗曼编码实现文件压缩和解压
来源:互联网 发布:c语言调用大漠插件 编辑:程序博客网 时间:2024/06/11 03:34
将压缩和解压放在了一个程序里面,并加入了进度显示功能。
并不完善,因为使用'\b'回退符来达到进度的数字能够变化,可是在需要操作的文件较小时会闪动比较严重,还会消耗多余的资源在显示上面,所以执行效率并不算高,可能在学会其他知识,比如图形化界面时我会再来改进它。
其他内容在旧版中有写,说多了都是泪 :http://blog.csdn.net/tookkke/article/details/50529838
- #include <cstdio> /************/
- #include <cstring> /* by */
- #include <iostream> /* kkke */
- #include <algorithm> /************/
- #include <queue> //2016.1.24
- #include <conio.h>
- #define MAX_WORD (65536)
- #define MAX_BYTE (256)
- using namespace std;
- typedef unsigned char BYTE;
- typedef unsigned short WORD;
- typedef unsigned long DWORD;
- typedef unsigned long long ULL;
- char in_file_name[80];
- char out_file_name[80];
- int cnt[MAX_BYTE*2];//number of each BYTE
- int filesize;
- ULL bit_cnt;
- int kkke[MAX_BYTE][MAX_BYTE];
- int kkke1[MAX_BYTE];
- int hehe[MAX_BYTE];
- const int tree_size=MAX_BYTE*2;
- struct the_tree{
- int son[2];
- }tree[MAX_BYTE*2];//root is 1
- struct cmp{
- bool operator()(int a,int b)
- {
- return cnt[a]>cnt[b];
- }
- };
- void read_data();
- void build_tree();
- void dfs(int k,int b);
- void output();
- void kdecompress()
- {
- system("cls");
- printf("解压\n");
- printf("请输入待解压文件名(不加.kcps):");
- scanf("%s",in_file_name);
- printf("请选择 输出文件名(会覆盖重名文件):\n");
- printf(" 1. %s\n",in_file_name);
- printf(" 2. 手动输入\n");
- char c;
- while((c=getch())!='1'&&c!='2');
- if(c=='1')strcpy(out_file_name,in_file_name);
- else
- {
- printf("请输入输出文件名:");
- scanf("%s",out_file_name);
- }
- strcat(in_file_name,".kcps");
- printf("将会生成 %s\n",out_file_name);
- printf(" 取消: ESC\n");
- printf(" 确认: 回车\n");
- while((c=getch())!=13&&c!=27);
- if(c==27)return;
- FILE *infp=fopen(in_file_name,"rb");
- if(infp==NULL)
- {
- printf("待解压文件 %s 打开失败\n",in_file_name);
- exit(1);
- }
- FILE *outfp=fopen(out_file_name,"wb");
- if(outfp==NULL)
- {
- printf("解压文件 %s 创建失败\n",out_file_name);
- exit(1);
- }
- for(int i=1;i<tree_size;i++)fread(&tree[i],sizeof(tree[i]),1,infp);
- fread(&bit_cnt,sizeof(bit_cnt),1,infp);
- BYTE a1;
- int a2=8;
- int nown=1;
- int b=0;
- system("cls");
- printf("正在解压文件... %3d.%02d%%",b/100,b%100);
- for(long long i=1;i<=bit_cnt;i++)
- {
- if(a2==8)
- {
- a2=0;
- fread(&a1,sizeof(a1),1,infp);
- }
- if(a1&((BYTE)1<<a2))nown=tree[nown].son[1];
- else nown=tree[nown].son[0];
- if(nown>=MAX_BYTE)
- {
- BYTE aa=nown-MAX_BYTE;
- fwrite(&aa,sizeof(aa),1,outfp);
- nown=1;
- }
- a2++;
- if(b==i*10000/bit_cnt)continue;
- b=i*10000/bit_cnt;
- for(int k=0;k<7;k++)putchar('\b');
- printf("%3d.%02d%%",b/100,b%100);
- }
- putchar('\n');
- if(fclose(infp))
- {
- printf("关闭输入文件 %s 失败\n",in_file_name);
- exit(1);
- }
- if(fclose(outfp))
- {
- printf("关闭输出文件 %s 失败\n",out_file_name);
- exit(1);
- }
- system("pause");
- }
- void kcompress()
- {
- system("cls");
- printf("压缩\n");
- printf("请输入待压缩文件名:");
- scanf("%s",in_file_name);
- printf("请选择 输出文件名(会覆盖重名文件):\n");
- printf(" 1. %s.kcps\n",in_file_name);
- printf(" 2. 手动输入(.kcps)\n");
- char c;
- while((c=getch())!='1'&&c!='2');
- if(c=='1')strcpy(out_file_name,in_file_name);
- else
- {
- printf("请输入输出文件名:");
- scanf("%s",out_file_name);
- }
- strcat(out_file_name,".kcps");
- printf("将会生成 %s\n",out_file_name);
- printf(" 取消: ESC\n");
- printf(" 确认: 回车\n");
- while((c=getch())!=13&&c!=27);
- if(c==27)return;
- read_data();
- build_tree();
- dfs(1,0);
- output();
- system("pause");
- }
- int main()
- {
- while(true)
- {
- system("cls");
- printf("@kkke随便写写的压缩程序:\n");
- printf("请置于待操作文件同一文件夹\n");
- printf("选择 1. 压缩\n");
- printf(" 2. 解压\n");
- char c;
- while((c=getch())!='1'&&c!='2');
- if(c=='1')
- {
- printf("已选择 压缩\n");
- printf(" 取消: ESC\n");
- printf(" 确认: 回车\n");
- while((c=getch())!=13&&c!=27);
- if(c==27)continue;
- kcompress();
- }
- else
- {
- printf("已选择 解压\n");
- printf(" 取消: ESC\n");
- printf(" 确认: 回车\n");
- while((c=getch())!=13&&c!=27);
- if(c==27)continue;
- kdecompress();
- }
- }
- return 0;
- }
- void output()
- {
- FILE *infp=fopen(in_file_name,"rb");
- if(infp==NULL)
- {
- printf("待压缩文件 %s 打开失败\n",in_file_name);
- exit(1);
- }
- FILE *outfp=fopen(out_file_name,"wb");
- if(outfp==NULL)
- {
- printf("压缩文件 %s 创建失败\n",out_file_name);
- exit(1);
- }
- for(int i=1;i<tree_size;i++)fwrite(&tree[i],sizeof(tree[i]),1,outfp);
- bit_cnt=0ULL;
- for(int i=0;i<MAX_BYTE;i++)bit_cnt+=(ULL)hehe[i]*(ULL)cnt[i+MAX_BYTE];
- fwrite(&bit_cnt,sizeof(bit_cnt),1,outfp);
- int b=0;
- system("cls");
- printf("生成文件总大小: %.3f KB\n",((double)bit_cnt+8.0*(double)sizeof(tree))/8192.0);
- printf("压缩率: %.3f%%\n",((double)bit_cnt+8.0*(double)sizeof(tree))/0.08/(double)filesize);
- printf("正在生成压缩文件... %3d.%02d%%",b/100,b%100);
- BYTE a;
- BYTE a1=0;
- int a2=0;
- for(int i=1;i<=filesize;i++)
- {
- fread(&a,sizeof(a),1,infp);
- for(int j=0;j<hehe[a];j++)
- {
- if(kkke[a][j])a1|=((BYTE)1<<a2);
- a2++;
- if(a2==8)
- {
- a2=0;
- fwrite(&a1,sizeof(a1),1,outfp);
- a1=0;
- }
- }
- if(b==(ULL)i*10000/filesize)continue;
- b=(ULL)i*10000/filesize;
- for(int k=0;k<7;k++)putchar('\b');
- printf("%3d.%02d%%",b/100,b%100);
- }
- putchar('\n');
- if(a2)fwrite(&a1,sizeof(a1),1,outfp);
- if(fclose(infp))
- {
- printf("关闭输入文件 %s 失败\n",in_file_name);
- exit(1);
- }
- if(fclose(outfp))
- {
- printf("关闭输出文件 %s 失败\n",out_file_name);
- exit(1);
- }
- }
- void dfs(int k,int b)
- {
- if(k>=MAX_BYTE)
- {
- k-=MAX_BYTE;
- for(int i=0;i<b;i++)kkke[k][i]=kkke1[i];
- hehe[k]=b;
- }
- else
- {
- kkke1[b]=0;
- dfs(tree[k].son[0],b+1);
- kkke1[b]=1;
- dfs(tree[k].son[1],b+1);
- }
- }
- void build_tree()
- {
- system("cls");
- printf("正在分析文件...\n");
- priority_queue<int,vector<int>,cmp>q;
- for(int i=MAX_BYTE+MAX_BYTE-1;i>=MAX_BYTE;i--)q.push(i);
- for(int i=MAX_BYTE-1;i;i--)
- {
- tree[i].son[0]=q.top();q.pop();
- tree[i].son[1]=q.top();q.pop();
- cnt[i]=cnt[tree[i].son[0]]+cnt[tree[i].son[1]];
- q.push(i);
- }
- }
- void read_data()
- {
- memset(cnt,0,sizeof(cnt));
- FILE *infp=fopen(in_file_name,"rb");
- if(infp==NULL)
- {
- printf("未找到待压缩文件\n");
- exit(1);
- }
- fseek(infp,0,SEEK_END);
- filesize=ftell(infp);
- fseek(infp,0,SEEK_SET);
- BYTE a;
- int b=0;
- system("cls");
- printf("文件总大小: %.3f KB\n",(double)filesize/1024.0);
- printf("正在读取文件... %3d.%02d%%",b/100,b%100);
- for(int i=1;i<=filesize;i++)
- {
- fread(&a,sizeof(a),1,infp);
- cnt[a+MAX_BYTE]++;
- if(b==(ULL)i*10000/filesize)continue;
- b=(ULL)i*10000/filesize;
- for(int k=0;k<7;k++)putchar('\b');
- printf("%3d.%02d%%",b/100,b%100);
- }
- if(fclose(infp))
- {
- printf("关闭输入文件失败\n");
- exit(1);
- }
- }
转载至
0 0
- 一个用C实现的哈弗曼编码实现文件压缩和解压
- 用哈弗曼编码实现文件压缩和解压
- java实现的文件压缩和解压
- Huffman编码实现压缩、解压文件
- C++实现霍夫曼编码文件压缩解压
- java中对文件解压和压缩的实现
- java程序实现对文件的压缩和解压
- Java实现Zip文件的解压和压缩_ZipUtil
- asp.net 实现文件的压缩和解压
- JAVA自己实现的文件压缩解压
- Java实现文件的压缩与解压
- Java实现文件的压缩与解压
- Java实现文件的压缩与解压
- 用哈弗曼编码实现文件压缩和解压(改进集成版1.0)
- 用java代码实现文件的zip压缩与解压
- Huffman编码压缩和解压文档,C++实现
- Java实现Gzip的压缩和解压
- java实现zip的压缩和解压
- Training Region-based Object Detectors with Online Hard Example Mining - cvpr 2016 oral
- 郝斌的C语言基础 030
- 中国城市级别划分
- CodeForces 392C
- 大话设计模式(Python版)--原型模式
- 一个用C实现的哈弗曼编码实现文件压缩和解压
- 3341 数据结构实验之二叉树二:遍历二叉树
- 屏幕分辨率 -- Web UI自动化大坑之一
- App架构设计
- LeetCode(198) House Robber
- 树莓派3入手环境搭建(QT+OpenCV)
- 【Spring从入门到精通】(一)Spring框架的整体架构
- 判断“资源字符串”是否可以构成“目标字符串”
- Linux中的crontab配置常用的日期格式以及详细事例