代码语言
.
CSharp
.
JS
Java
Asp.Net
C
MSSQL
PHP
Css
PLSQL
Python
Shell
EBS
ASP
Perl
ObjC
VB.Net
VBS
MYSQL
GO
Delphi
AS
DB2
Domino
Rails
ActionScript
Scala
代码分类
文件
系统
字符串
数据库
网络相关
图形/GUI
多媒体
算法
游戏
Jquery
Extjs
Android
HTML5
菜单
网页交互
WinForm
控件
企业应用
安全与加密
脚本/批处理
开放平台
其它
【
C
】
小文件解压缩程序
作者:
李朝强
/ 发布于
2015/5/6
/
710
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 /** *HuffmanTree类:利用Huffman树对串进行编码与译码(Huffman编码) *@author Yc *@time 2015-5-5 13:31:26 */ #include<vector> #include<iostream> using namespace std; struct HuffmanNode { friend istream& operator >>(istream &is,HuffmanNode& hn) { cout << "请输入字符:"; is >> hn.data; cout << "请输入该字符比重:"; is >> hn.weight; return is; } char data; //编码数据 局限:汉字? double weight; //该编码数据所占比重 int parent, lchild, rchild; //该结点的父结点,左孩子结点和右孩子结点 }; class HuffmanTree{ vector<HuffmanNode> hufftree; //Huffman树 存储结构,线性结构(向量) int n; //叶子结点数 /* *在huffman的前n个向量中,找到最小比重的结点索引以及次小比重的结点索引下标 *@param least(out) 最小比重结点索引 *@param less(out) 次小比重结点索引 */ void SelectSmall(int& least, int& less, int n) { if (n < 2) return;//健壮性 int j; for ( j = 0; j < n; j++)//默认把前两项未处理的叶子结点为least和less { if (hufftree[j].parent == -1) { least = j; break; } } for ( j = least+1; j < n; j++) { if (hufftree[j].parent == -1) { less = j; break; } } if (hufftree[less].weight < hufftree[least].weight) { int tmp = least; least = less; less = tmp; } for (int i = j + 1; i < n; i++)//将前两项后的项依次与前两项比较 { if (hufftree[i].parent != -1) continue; if (hufftree[i].weight < hufftree[less].weight) { if (hufftree[i].weight < hufftree[least].weight) { less = least; least = i; }//将次小赋值为原来最小的,现在最小赋值为i else less = i; //将次小赋值为i } } } public: HuffmanTree(){} /* *HuffmanTree构造函数 *@param leafs 存储叶子结点的向量(动态数组) */ HuffmanTree(vector<HuffmanNode> &leafs){ n = leafs.size(); hufftree.resize((n<<1)-1); for (int j = 0; j < n; j++)//将叶子结点存入hufftree { hufftree[j].data = leafs[j].data; hufftree[j].weight = leafs[j].weight; hufftree[j].parent = hufftree[j].lchild = hufftree[j].rchild = -1; } for (int i = n; i < 2 * n - 1; i++)//将其他n-1个非叶子结点存入hufftree { int least, less; SelectSmall(least,less,i); //找到最小,次小索引 hufftree[least].parent = hufftree[less].parent = i; hufftree[i].parent = -1; hufftree[i].lchild = least; hufftree[i].rchild = less; hufftree[i].weight = hufftree[least].weight + hufftree[less].weight; } } ~HuffmanTree(){ } void Show()//打印叶子结点data和索引 { for (int i = 0; i < n; i++) cout << hufftree[i].data << ","<<i<<" "; cout << endl; } /* *按索引编码 *@param i 取编码的索引值 *@return 索引i的编码值 */ vector<char>GetCode(int i){//从叶子结点开始,然后沿着父指针上溯,将编码头插入向量中,直至无父结点 vector<char> code; while (hufftree[i].parent != -1) { int par = hufftree[i].parent; if (hufftree[par].lchild == i) code.insert(code.begin(), 0); else code.insert(code.begin(), 1); i = par; } return code; } /* *按字节编码 *@param ch 取编码的字节 *@return ch的编码值 */ vector<char>GetCode(char ch){//从叶子结点开始,然后沿着父指针上溯,将编码头插入向量中,直至无父结点 int size = hufftree.size(); for (int i = 0; i < size;i++)//遍历hufftree 查找ch的索引 if (ch == hufftree[i].data) return GetCode(i); } /* *译码 *@param src 需译码的编码 *@return 译码的结果 */ string Decode(vector<char>& src){ string dest = ""; int root = hufftree.size() - 1; int p = root; for (int i = 0; i < src.size(); i++) { if (src[i] == 0) p = hufftree[p].lchild; else p = hufftree[p].rchild; if (hufftree[p].lchild == -1 && hufftree[p].rchild == -1) { dest += hufftree[p].data; p = root; } } return dest; } }; // Huffman.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "HuffmanTest.h" #include <iostream> #include <string> using namespace std; #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif CWinApp theApp; int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { if(!AfxWinInit(::GetModuleHandle(NULL),NULL,::GetCommandLine(),0)) return 1; HuffmanTree hmt; //huffmantree对象(针对一个文件) string filename = ""; //压缩文件的绝对文件路径 vector<char> totalCode; //合并后存储的01序列 while (1) { cout<<"***********************************************"<<endl; cout<<"* *"<<endl; cout<<"* 我的小文件解压缩软件 *"<<endl; cout<<"* ——Moyu *"<<endl; cout<<"* *"<<endl; cout<<"* 1.压缩 *"<<endl; cout<<"* 2.解压 *"<<endl; cout<<"* 3.退出 *"<<endl; cout<<"* *"<<endl; cout<<"* 注意: 解压前必须先压缩 *"<<endl; cout<<"* 退出程序后需要重新压缩 *"<<endl; cout<<"* *"<<endl; cout<<"***********************************************"<<endl; int cmd; cin>>cmd; switch (cmd) { case 1: Compress(hmt, filename, totalCode); break; case 2: if (filename == "") { cout << "Error: 未压缩" << endl; break; } Decompress(hmt, filename, totalCode); totalCode.clear(); break; case 3: exit(1); default: cout << "error" << endl; } } return 0; } 4. [文件] HuffmanTest.h ~ 5KB 下载(0) ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 #if !defined(AFX_HUFFMAN_H__9DB78DB5_9C71_42DF_9868_BDC1B8899AAE__INCLUDED_) #define AFX_HUFFMAN_H__9DB78DB5_9C71_42DF_9868_BDC1B8899AAE__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "resource.h" #include "Huffman.h" #include <fstream> #include <map> #include <string> #include <iostream> #include <iomanip> using namespace std; #endif // !defined(AFX_HUFFMAN_H__9DB78DB5_9C71_42DF_9868_BDC1B8899AAE__INCLUDED_) //压缩时主函数调用的函数 void Compress(HuffmanTree& ht, string &filename, vector<char>& totalCode) { CString savefilter="压缩文件(*.huff)|*.huff||"; CString openfilter="所有文件(*.*)|*.*||"; CFileDialog openDlg(TRUE,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,openfilter); CFileDialog saveDlg(FALSE,NULL,"New.huff",OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,savefilter); if(openDlg.DoModal()!=IDOK) return; ofstream outfile; ifstream infile; infile.open(openDlg.GetPathName(), ios::in | ios::binary); if (!infile){ cout << "error" << endl; exit(1); } streampos start = infile.tellg(); // save current position infile.seekg(0,ios::end); streampos end=infile.tellg(); //文件最后位置 infile.seekg(start); // restore saved position vector<HuffmanNode> vec;//存放各字节的次数 char c; //将第一个字节写入vec infile.read(&c, 1); HuffmanNode node; node.data = c; node.weight = 1; vec.push_back(node); while (infile.tellg()!=end)//!infile.eof()该判断条件最后一个字节会读2次 //统计各字节出现次数\比重 { char ch; infile.read(&ch, 1); int len = vec.size(); int i; bool flag=false; for (i = 0; i < len; i++) { if (vec[i].data == ch) { flag = true; vec[i].weight++; break; } } if (flag==false) { HuffmanNode node; node.data = ch; node.weight = 1; vec.push_back(node); } } cout << "是否保存压缩文件?(y/n)" << endl; char cmd; cin>>cmd; if (cmd == 'n' || cmd == 'N') return; if (saveDlg.DoModal() != IDOK) return; outfile.open(saveDlg.GetPathName(), ios::out | ios::binary); filename = saveDlg.GetPathName(); if (!outfile){ cout << "error" << endl; exit(1); } ht=HuffmanTree(vec); //获取HuffmanTree对象 infile.seekg(0,ios::beg); //将文件指针指向文件开头 // vector<char> totalCode; //合并后存储的01序列 while (!infile.eof())//2-> (infile.tellg() != end) { char ch; infile.read(&ch, 1); if (infile.fail()) break; //读到最后 读取出错 //用第二种判断方法则不需要判断 vector<char>code = ht.GetCode(ch); totalCode.insert(totalCode.end(), code.begin(), code.end());//将各个ch的编码合并在一起 } infile.close(); unsigned int totsize = totalCode.size(); unsigned int unit =( totsize >> 3 ) + 1; long filesize = end; outfile.write((char*)(&filesize), sizeof(long));//将文件的大小写入压缩文件第一个数据 为了防止满足8位配对造成的错误解压 for(int j=0;j<unit;j++)//然后每8位编码合成一个字节 写入文件 { unsigned char uch = 0; unsigned int begin = j << 3; //每8个为一个单元 begin为每个单元的第一个索引:2*2*2*j 0->0 1->8 2->16 for (int i = 0; i < 8; i++) { if (begin + i>=totsize) //越界了 uch = uch << 1; //左移1位 右边添0 else { if (totalCode[begin + i] == 0) uch = uch << 1; //左移1位 右边添0 else uch = (uch << 1) | 1; //左移1位 右边添1 } } outfile<<uch; //写入文件 } cout << "压缩成功!" << endl; outfile.seekp(0, ios::end); streampos end1 = outfile.tellp(); //文件最后位置 cout << "压缩前文件大小:" << filesize << " Bytes\n"; cout << "压缩后文件大小:" << end1 << " Bytes\n"; cout << "压缩率为:" << (end1 * 100 / filesize) << "%" << endl; outfile.close(); system("pause"); } //解压缩时主函数调用的函数 void Decompress(HuffmanTree& ht, string filename, vector<char> totalCode) { CString openfilter = "压缩文件(*.huff)|*.huff||"; CString savefilter = "所有文件(*.*)|*.*||"; CFileDialog openDlg(TRUE, NULL, filename.c_str(), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, openfilter); CFileDialog saveDlg(FALSE, NULL,"decompress" , OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, savefilter); if (openDlg.DoModal()!= IDOK) return; ofstream outfile; ifstream infile; infile.open(openDlg.GetPathName(), ios::in | ios::binary); long filesize; infile.read((char *)(&filesize), sizeof(long)); //读原文件大小 string content = ht.Decode(totalCode); while(content.size() > filesize) //最后面多余的0也被解码 content=content.substr(0,content.length()-1);//pop_back(); cout << "是否保存解压文件?(y/n)" << endl; char cmd; cin >> cmd; if (cmd == 'n' || cmd == 'N') return; if (saveDlg.DoModal() != IDOK) return; outfile.open(saveDlg.GetPathName(), ios::out | ios::binary); outfile.write(content.c_str(),content.size()); outfile.flush(); cout << "解压成功!" << endl; outfile.close(); system("pause"); }
试试其它关键字
小文件解压
压缩程序
同语言下
.
获取手机通讯录 iOS去除数字以外的所有字符
.
异步加载音乐等资源
.
交通罚单管理系统
.
freemark实现,简单的替换
.
计算斐波那契数列
.
base64解码 包括解码长度
.
图像显示
.
冒泡排序
.
输入十进制数,输出指定进制
.
链式栈
可能有用的
.
C#实现的html内容截取
.
List 切割成几份 工具类
.
SQL查询 多列合并成一行用逗号隔开
.
一行一行读取txt的内容
.
C#动态修改文件夹名称(FSO实现,不移动文件)
.
c# 移动文件或文件夹
.
c#图片添加水印
.
Java PDF转换成图片并输出给前台展示
.
网站后台修改图片尺寸代码
.
处理大图片在缩略图时的展示
李朝强
贡献的其它代码
(
10
)
.
异常处理示例
.
小文件解压缩程序
.
Spring MVC自动转换JSON日期
.
php模板引擎
.
struts迭代map并显示值
.
rc4加密解密
.
运用委托手动创建ORM
.
洗牌算法
.
微信公众平台开发人员POSTXML助手
.
Java图片上传代码
Copyright © 2004 - 2024 dezai.cn. All Rights Reserved
站长博客
粤ICP备13059550号-3