📄 ltyzipdlg.cpp
字号:
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 + -