⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unredfun.cpp

📁 利用shannon定理对文件进行压缩与解压缩
💻 CPP
字号:
#include <fstream.h>
#include <string.h>
#include <math.h>
#include "unredfun.h"

/*-------------------------------------------------------
目的:读取文件头中有关解码的信息,并将其保存到类变量中
输入:无
输出:bool 读表头成功返回true,否则返回false
-------------------------------------------------------*/
bool FUReduce::ReadFHead()
{
	if(m_fileName != NULL)
	{
		ifstream in(m_fileName, ios::binary | ios::nocreate);
		unsigned char tempCh = 0x00;
		in.read(&tempCh, 1);							// 读表头第一个字节(编码规则个数)
		m_codeNum = tempCh + 1;
		if(m_codeNum == 0)
		{
			return false;
		}
		m_pCode = new CRule [m_codeNum];				// 为编码规则分配空间
		m_pCodeLength = new unsigned char [m_codeNum];	// 存放各码字个长度
		int i = 0;		// 指示第i+1组编码规则
		int j = 0;		// 指示码字中第j个码元
		int time = 0;
		char* str = NULL;
		bool flag = true;
		while(i<m_codeNum)
		{
			in.read(&m_pCode[i].fByte,1);
			in.read(&m_pCodeLength[i], 1);
			m_pCode[i].code = new char[m_pCodeLength[i]+1];
			for(int t=0; t<m_pCodeLength[i]; t++)
			{
				m_pCode[i].code[t] = '\0';
			}
			j = 0;
			time = 0;
			unsigned char bitCode = 0x00;		// 存放码字
			in.read(&bitCode, 1);
			flag = true;
			while(flag)
			{	
				str = Trans(bitCode);
				if((m_pCodeLength[i]-time*8)<=8)
				{
					for(; j<m_pCodeLength[i]; j++)
					{
						m_pCode[i].code[j] = str[j-time*8];
					}
					m_pCode[i].code[j] = '\0';
					flag = false;
				}
				else
				{
					if(0!=strlen(m_pCode[i].code))
					{
						strcat(m_pCode[i].code, str);
					}
					else
					{
						strcpy(m_pCode[i].code, str);
					}
					j+=8;
					time++;
					in.read(&bitCode, 1);
				}
			}
			i++;
		}
		m_here = in.tellg();		// 记录编码规则的结尾处
		return true;
	}
	else
	{
		return false;
	}
}

/*-------------------------------------------------------
目的:构造函数,初始化对象
输入:char* FileName 待解压文件名
输出:无
-------------------------------------------------------*/
FUReduce::FUReduce(char* FileName)
{
	strcpy(m_fileName, FileName);
	m_pCodeLength = NULL;
	m_pCode = NULL;
	m_codeNum = 0;
	m_pT = NULL;
}

/*-------------------------------------------------------
目的:构造函数,初始化对象
输入:char* FileName 待解压文件名
输出:无
-------------------------------------------------------*/
FUReduce::~FUReduce()
{
	m_fileName[0] = '\0';
	m_pCodeLength = NULL;
	m_pCode = NULL;
	m_codeNum = 0;
	m_pT = NULL;
}

/*-------------------------------------------------------
目的:构造译码树
输入:无
输出:构造树成功返回true;否则返回false;
-------------------------------------------------------*/
bool FUReduce::CreatDecodeTree()
{
	if(m_fileName==NULL)
	{
		return false;
	}
	else
	{
		m_pT = new DecodeTree;				// 头结点
		m_pT->data = '\0';
		m_pT->lchild = NULL;
		m_pT->rchild = NULL;
		DecodeTree* prePoint = m_pT;		// 指向前一个结点
		DecodeTree* curPoint = m_pT;		// 指向当前结点

		int i = 0, j = 0;
		for(i=0; i<m_codeNum; i++)
		{
			j = 0;							// 指示码字长度
			while(j<m_pCodeLength[i])
			{
				if(m_pCode[i].code[j] == '1')
				{					
					if(curPoint->lchild == NULL)
					{
						curPoint = new DecodeTree;
						curPoint->data = '1';
						curPoint->lchild = NULL;
						curPoint->rchild = NULL;
						prePoint->lchild = curPoint;
						prePoint = curPoint;
					}
					else
					{
						curPoint = curPoint->lchild;
						prePoint = curPoint;
					}
				}
				else
				{
					if(curPoint->rchild == NULL)
					{
						curPoint = new DecodeTree;
						curPoint->data = '0';
						curPoint->lchild = NULL;
						curPoint->rchild = NULL;
						prePoint->rchild = curPoint;
						prePoint = curPoint;
					}
					else
					{
						curPoint = curPoint->rchild;
						prePoint = curPoint;
					}
				}
				j++;
			}
			curPoint->lchild = curPoint->rchild = new DecodeTree;
			curPoint->lchild->data = m_pCode[i].fByte;		// 将码字对应的数据做为译码树的叶子结点
			curPoint->lchild->lchild = NULL;
			curPoint->lchild->rchild = NULL;
			curPoint = prePoint = m_pT;

		}
		return true;
	}
}

/*-------------------------------------------------------
目的:将文件解压缩,恢复成源文件
输入:char* destFile 解压后文件的存贮路径
输出:解压缩成功返回true;否则返回false;
-------------------------------------------------------*/
bool FUReduce::UnReduceSaving(char* destFile)
{
	if(destFile == NULL)
	{
		return false;
	}
	else
	{
		ofstream out(destFile, ios::binary);
		ifstream in(m_fileName, ios::binary);
		in.seekg(m_here);		// 跳过待解压文件的编码规则
		DecodeTree* prePoint = m_pT;
		DecodeTree* curPoint = m_pT;
		unsigned char biBuffer = '\0';
		int i = 0;		// 标识数据块第i位
		in.read(&biBuffer, 1);
		while(!in.eof())
		{
			while(curPoint->lchild!=curPoint->rchild)
			{
				if(i<8)
				{
					if(GetBit(biBuffer, i+1) == 1)
					{
						prePoint = curPoint;
						curPoint = curPoint->lchild;
						i++;
					}
					else
					{
						prePoint = curPoint;
						curPoint = curPoint->rchild;
						i++;
					}
				}
				else 		// 码字长度大于8
				{
					in.read(&biBuffer, 1);
					if(!in.eof())
					{
						i = 0;
					}
					else
					{
						return true;
					}
				}
			}
			out<<curPoint->lchild->data;
			curPoint = prePoint = m_pT;
		}
		return true;
	}
}

/*-------------------------------------------------------
目的:从一个数据块中取第n位的值
输入:unsigned char ch 数据块的值
	  int n	要取的位
输出:unsigned char 返回的第n位的值
-------------------------------------------------------*/
unsigned char FUReduce::GetBit(unsigned char ch, int n)
{
	return (ch & (1<<(8-n)))>>(8-n);
}

/*-------------------------------------------------------
目的:把一个数据块按位转换成字符串
输入:unsigned char block 一字节数据块
输出:char* 指向字符串的指针
-------------------------------------------------------*/
char* FUReduce::Trans(unsigned char block)
{
	char* ch = new char[9];
	unsigned char mask = 0x01;
	unsigned char t = 0x00;
	for(int i=0; i<8; i++)
	{
		mask <<= 8-i-1;
		t = (block & mask)>>(8-i-1);
		if(t==1)
		{
			ch[i] = '1';
		}
		else
		{
			ch[i] = '0';
		}
		mask = 0x01;
		t = 0x00;
	}
	ch[i] = '\0';
	return ch;
}

/*-------------------------------------------------------
目的:打印测试结果
输入:无
输出:无
-------------------------------------------------------*/
void FUReduce::TestRusult()
{
	cout<<"生成的译码树:"<<endl;
	cout<<"xi"<<'\t'<<'l'<<'\t'<<'r'<<'\t'<<'w'<<endl;
	cout<<"----------------------------------------"<<endl;
	PutTree(m_pT);
	cout<<"----------------------------------------"<<endl;

}

/*-------------------------------------------------------
目的:打印译码树
输入:DecodeTree* T 译码树头结点
输出:无
-------------------------------------------------------*/
void FUReduce::PutTree(DecodeTree* T)
{
	static int i = 0;
	i++;
	if(T&&(T->lchild!=NULL||T->rchild!=NULL))
	{
		cout<<'x'<<i<<'\t'<< hex <<T->lchild<<'\t'<<T->rchild<<'\t'<<T->data<<endl;
		PutTree(T->lchild);
		PutTree(T->rchild);
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -