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

📄 ltyzipdlg.cpp

📁 本程序使用C++编写
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	   m_iFileFlag = 2;
	     
	}
}

void CltyzipDlg::OnBnClickedJieYa()
{
	// TODO: Add your control notification handler code here
	if (11 == m_iFileFlag)
	{
	   m_message = "正在解压文件,请稍候…";
	   UpdateData(FALSE);
	   m_ProgressCtrlj.SetRange(0,1000);
	   m_ProgressCtrlj.SetStep(100);
	   for(int progressctrl = 0;progressctrl<=1000;)m_ProgressCtrlj.SetPos(progressctrl++);
	   TranslateCodes(m_jieyadizhi,JieYaSaveAddr);
	   m_message = "文件解压完毕!";
	   UpdateData(FALSE);
	   m_iFileFlag = 12;
	}
	else if (12 == m_iFileFlag)
	{
		MessageBox(_T("文件已解压!"),_T("错误"),MB_OK | MB_ICONERROR);
	}
	else
	{
    	MessageBox(_T("文件解压时地址操作错误!"),_T("错误"),MB_OK | MB_ICONERROR);
	}
}
float CltyzipDlg::OpenandCloseFile(CString OpenFile, CString &CloseFile)
{
    	//打开一个待压缩文件,提供压缩后存储的地址
	char Temp[iMax];short isNumofBits;
	float fCompre = 0 ;
	ifstream infile(OpenFile, ios::in|ios::binary);
	do 
	{
		infile.read(Temp,iMax);
		isNumofBits = infile.gcount();//每次实际读入的字节数
		for (int iPos = 0; iPos < isNumofBits; iPos++)
		{
			++hufcode.hArray[Temp[iPos] + 128].iWeight;  //统计每个节点在ASCII中的出现频率
		}
		
	} while(isNumofBits == iMax); //每次读入1024个字节
	
	hufcode.CreateHaffmanTree(hufcode.hArray); //使用得到的权值构建哈夫曼树,这里用矩阵实现
	hufcode.EnHaffmanCode(hufcode.hArray,hufcode.codes);//对已经构建好的哈夫曼树的每个叶结点进行编码
    fCompre = ChangtoCode(OpenFile,CloseFile);//把所有的内容都按照编码存入一个新文件

	infile.clear();//清理文件读取和写入指针
	infile.close();//关闭文件
	return fCompre;
}
float CltyzipDlg::ChangtoCode(CString OpenFile, CString &CloseFile)
{
	ifstream ifile(OpenFile,ios::in | ios::binary); //再次读入待压缩的文件
	ofstream outfile(CloseFile, ios::out | ios::binary);//保存压缩文件	
	//////////////////////////////进度条的准备工作/////////////////////////////////////////////////

	//rect rectangle;rectangle.lenth = 5;rectangle.wide = 2;
	int progressctrl = 0;
	//dlg.m_progressctrl.Create(PBS_SMOOTH,rectangle,CltyzipDlg,IDC_PROGRESS1);
	ifile.seekg(0,ios::end);
	m_progressctrl.SetRange(0,(int)(ifile.tellg()/1024));
	ifile.seekg(0,ios::beg);
	m_progressctrl.SetStep(100);
	////////////////////////////////////////////////////////////////////
	for(int iWright = 0; iWright < 256; iWright++)
	{
		outfile.write((char*)&hufcode.hArray[iWright].iWeight,4); //在压缩文件中存入每个叶子节点的权值
	}
	///////////////////////////////////// //构建一个char[4]的数组,用来存入待压缩文件的后缀名/////////////////////////////////////
	char FileName[4] = {'*','*','*','*'};
	int FileNameLength = OpenFile.GetLength();
	for (int iFileNamePos = ( FileNameLength - 4), NewFilePos = 0; iFileNamePos < FileNameLength; iFileNamePos++)
	{
		if ('.' == OpenFile[iFileNamePos])
		{
			continue;  //跳过文件后缀名前的点
		}
		else
		{
			FileName[NewFilePos] = (char)OpenFile[iFileNamePos];
			NewFilePos++;
		}
	}
    outfile.write(FileName,4);//在压缩文件中存入待压缩文件的后缀名
	/////////////////////////////////在压缩文件中存入待压缩文件的正文!/////////////////////////////////////////////////////////////////////
	int i = 0,h,flag =1;
	char ArrayChar[128],ArrayCode[1024];
    unsigned char bit;
	char Temp[iMax];    short isNumofBits;
	do 
	{
		m_progressctrl.SetPos(progressctrl++);
		ifile.read(Temp,iMax);  //每次在待压缩文件中读入1024个字节
		isNumofBits = ifile.gcount();//每次实际的读出字节的数目
		for (int iPos = 0; iPos < isNumofBits; iPos++)
		{
            bit = Temp[iPos]+128;//每个字节的ASCII码都加上128,使其全部在正数中	
			for (int start = hufcode.codes[bit].iStart + 1; start < 255; )//start 为有编码存在的地方
			{
                ArrayCode[i++] = hufcode.codes[bit].Bit[start++];

				if (i >= 1024)//在数组中存入了1024个后就开始将其转换为char数组,存入压缩文件
				{				
		          	for (int j=0; j < 128; j++) //每次都操作8个0或者1的数字(将其作为二进制对待)
					{
						h = j*8;
						ArrayChar[j] = 
							char(ArrayCode[h+0]*128 + ArrayCode[h+1]*64 +
							ArrayCode[h+2]*32 + ArrayCode[h+3]*16 + 
							ArrayCode[h+4]*8 +ArrayCode[h+5]*4 + 
							ArrayCode[h+6]*2 + ArrayCode[h+7] - 128);
						
					}//每一位根据其在二进制中的位置对其进行相应的二进制转换
					outfile.write(ArrayChar,128);//存入压缩文件
					i = 0;
				}
			}
			
		}
	} while(isNumofBits == iMax);//如果读入的数据不足iMax也就是1024位,结束循环

//////////////处理在ArrayCode[1024]中不足1024个数时,对其进行的转换为char的工作/////////////////////////////

	int ElseTimes = i/8;//得到可以直接转换为char的个数
	int j=0;
	for (; j < ElseTimes; j++)
	{
		h = j*8;
		ArrayChar[j] = 
			char(ArrayCode[h+0]*128 + ArrayCode[h+1]*64 +
			ArrayCode[h+2]*32 + ArrayCode[h+3]*16 + 
			ArrayCode[h+4]*8 +ArrayCode[h+5]*4 + 
			ArrayCode[h+6]*2 + ArrayCode[h+7] - 128);
		
	}
	////////////////////////////////对不足八位的数处理////////////////////////////
	m_progressctrl.SetPos(progressctrl);
	int Else = i % 8;//得到不足八位的数 
	int ChangeBits = 0,swa = 1;
	unsigned char sum = 0;
    for ( int t=ElseTimes*8; t < i; t++, swa *= 2)
    {
		sum += ArrayCode[t] * (128 / swa);
    }
	if (swa != 1)
	{
		ArrayChar[j] = char(sum-128);
		ChangeBits = 1;
	}
	outfile.write(ArrayChar,ElseTimes + ChangeBits);

	char last = 0;//在不足八位时,对其补充的0的个数
	if (Else != 0)
	{
		last = (char)(8 - Else);
	}
	outfile << last;//将加入的0的个数读入文件
///////////////////////////////////////////////////////////计算文件的压缩率////////////////
    ifile.clear();
	ifile.seekg(0,ios::end);  
	double  ldOriginSize = ifile.tellg();//计算原文件的长度,保存在ldOriginSize中
	outfile.clear();
	outfile.seekp(0,ios::end);
	double ldChangedSize = outfile.tellp();//计算压缩文件的长度,保存在ldChangedSize中
	ifile.close();
	outfile.close();//关闭文件
	
	return (float)((ldOriginSize - ldChangedSize)/ldOriginSize)*100;//计算文件的压缩率并且返回
}
void CltyzipDlg::TranslateCodes(CString OpenFile, CString &CloseFile)
{
  ifstream infile(OpenFile,ios::in | ios::binary);
	ofstream outfile(CloseFile,ios::out | ios::binary);
	//////////////////////////////进度条的准备工作/////////////////////////////////////////////////

	//rect rectangle;rectangle.lenth = 5;rectangle.wide = 2;
	int progressctrl = 0;
	//dlg.m_progressctrl.Create(PBS_SMOOTH,rectangle,CltyzipDlg,IDC_PROGRESS1);
	infile.seekg(0,ios::end);
	m_ProgressCtrlj.SetRange(0,(int)(infile.tellg()/1024));
	infile.seekg(0,ios::beg);
	m_ProgressCtrlj.SetStep(100);
	////////////////////////////////////////////////////////////////////
	for (int iRead = 0; iRead < 256; iRead++)
	{
		infile.read((char*)&hufcode.hArray[iRead].iWeight,4);  //把每个节点的权值读出文件
	}
    hufcode.CreateHaffmanTree(hufcode.hArray);  //再次使用这些权值建立一个哈夫曼树
///////////////////////////////////////////得到要保存文件的文件名(该文件名没有包含后缀名)/////////////////////
	char FileName[4];
	infile.read(FileName,4); //文件的后缀名一共存了4个字节,是因为当前的文件的后缀名主要是2到4位
	CloseFile += '.';//给要保存的文件名后面加上点
	for ( int i = 1,iOriginNamePos = 0; i < 5 ;i++ )
	{//给要保存的文件后面加上后缀名
		if ('*' == FileName[iOriginNamePos])//跳过*号
		{
			break;
		}
		CloseFile += FileName[iOriginNamePos++];
	}
	CloseFile += _T('\0'); //给要保存的文件名末尾加上结束符号
	int iNumofBits,j, num = 0, pos = 510;
	char TranTemp[512],Final[1024],t; 
	int  *iTemp = new int[4096];//用来存储TranTemp[512]转换成二进制代码的数组
	do 
	{
		m_ProgressCtrlj.SetPos(progressctrl++);
		infile.read(TranTemp,512);  //每次从文件中得到512个字节
		iNumofBits = infile.gcount();//每次从文件中实际得到的字节数
		
		for (int i = 0; i < iNumofBits; i++)
		{
			unsigned char value = TranTemp[i] + 128; 
			j = i * 8;
			for (int k = j+8-1; k >= j; k--)
			{ 
				iTemp[k] = value%2;  //使用求余数的方法得到每个字节的二进制代码
				value = value / 2;
			}
			
		}
		int TotalTimes = iNumofBits*8;
		if (iNumofBits != 512 && iNumofBits != 0) //如果是最后一次读入文件
		{
			int Last = 0;
			infile.clear();
		    infile.seekg(-1,ios_base::end);//最后一次就把读文件的指针前移一位
    		infile>>Last;	//读出最后存在文件最后一位的数值
			TotalTimes -= (Last + 8);//这个数值就是文件压缩时的存入的为补成最后一个字符所补足的0的个数
		}
	    for(int times = 0;times<TotalTimes;	times++)//这里使用的是递推的方法求得其叶子节点
        {
           int flag = iTemp[times];
		   if (flag == 0)
		   {
			   pos = hufcode.hArray[pos].iLeftChild;  //在建立的哈夫曼树种查找被压缩的文件的实际每个字符
		   }
		   else if (flag == 1)
		   {
			
			  pos =hufcode.hArray[pos].iRightChild;
		   }
		    if (hufcode.hArray[pos].iLeftChild == -1 || hufcode.hArray[pos].iRightChild == -1)
		   {
			   t = char(pos + 128);
			   Final[num] = t;//读入Final[1024]数组中
			   pos = 510;
			   ++num;
			   if(num == 1024)//当满足了1024个元素时,一起读到解压后的文件中 
			   {
				   outfile.write(Final,1024);
				   num = 0;
			   }
		   }
        }
       
		
	} while(iNumofBits == 512);//每次读入的不足512位那就结束循环
	outfile.write(Final,num);
	delete []iTemp;
	infile.clear();
	outfile.clear();
	infile.close();
	outfile.close();
}

⌨️ 快捷键说明

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