📄 haffmandlg.cpp
字号:
}
c=p;
p=ht[p].parent;
}
hcd[i]=new char[n-start];
strcpy(hcd[i],&hc[start]);
}
delete[] hc;
}
void function::WriteFile(char *tmp)
{
int i;
for(i=0;i<8;i++)
cout<<tmp[i];
cout<<' ';
tmp="";
}
unsigned char function::ConvertBinary(char *tmp)
{
char ch=0;
int i;
for(i=0;i<8;i++)
{
ch=(unsigned char)pow(2.0,8-i-1)*(tmp[i]-48)+ch;
}
return ch;
}
//////////////////压缩写入文件//////////////////
void function::ConvertFile(HCode hcd[],string fileadd,string fileadd2)
{
fstream infile(fileadd.c_str(),ios::in|ios::binary);
fstream outfile(fileadd2.c_str(),ios::out|ios::binary);
char ch;
/////////////写入哈夫曼树//////////////
ch=nodenum;
outfile.write(&ch,1); ///写入结点数
ch=8;
outfile.write(&ch,1); ///写入补位数
codelen=0;
outfile.write((char *)&codelen,4); //写入压缩后的文件的哈夫曼编码总长度
int h=0;
for(h=0;h<nodenum;h++)
{
outfile.write((char*)&ht[h].data,sizeof(char));
outfile.write((char*)&ht[h].weight,sizeof(int));
}
char tmp[8]; //设置缓冲区
char outbuffer[bufferlen]; //设置写入缓冲区
char *tmpcd;
int i=0,j,k,last=0;
char inbuffer[bufferlen];
int readlen=0;
h=0;
do
{
infile.read(inbuffer,bufferlen);
readlen=infile.gcount();
tmpcd=hcd[maplist[(unsigned char)inbuffer[i]]];
for(i=0;i<readlen;)
{
for(j=last;j<8 && *tmpcd!='\0';j++)
{
tmp[j]=*tmpcd;
tmpcd++;
}
if(j==8 && *tmpcd=='\0')
{
last=0;
i++;
ch=ConvertBinary(tmp);
outbuffer[h]=ch;
h++;
codelen++; //压缩文件长加度加一
if(h==bufferlen)
{
outfile.write(outbuffer,bufferlen);
h=0;
}
if(i<readlen) tmpcd=hcd[maplist[(unsigned char)inbuffer[i]]];
else
{
i=0;
break;
}
}
else if(j<8 && *tmpcd=='\0')
{
last=j;
i++;
if(i<readlen) tmpcd=hcd[maplist[(unsigned char)inbuffer[i]]];
else
{ i=0;
break;
}
}
else if(j==8 && *tmpcd!='\0')
{
last=0;
ch=ConvertBinary(tmp);
outbuffer[h]=ch;
h++;
codelen++; //压缩文件长加度加一
if(h==bufferlen)
{
outfile.write(outbuffer,bufferlen);
h=0;
}
}
}
}
while(readlen==bufferlen);
if(j==8 && readlen<bufferlen)
{
outfile.write(outbuffer,h);
}
else if(j<8 && readlen<bufferlen)
{
for(k=j;k<8;k++)
{
tmp[k]='0';
}
ch=ConvertBinary(tmp);
outbuffer[h]=ch;
h++;
outfile.write(outbuffer,h);
codelen++; //压缩文件长加度加一
}
ch=8-j;
rearnum=8-j;
outfile.seekp(1,ios::beg);
outfile.write(&ch,1); //写入真正的补位数
outfile.seekp(2,ios::beg);
outfile.write((char*)&codelen,4); //写入真正的压缩后的文件的哈夫曼编码总长度长度
outfile.close();
infile.close();
}
/////////////从文件解压////////////////////
void function::DecompressionFile(string fileadd2,string fileadd3)
{
fstream infile(fileadd2.c_str(),ios::in|ios::binary);
fstream outfile(fileadd3.c_str(),ios::out|ios::binary);
/////////////////读出哈夫曼树的数据/////////////
int h=0;
char buffer[bufferlen]; //读入文件的缓冲区
char outbuffer[bufferlen]; //写入文件的缓冲区
infile.read(buffer,1);
nodenum=(unsigned char)*buffer;//哈夫曼树结点数
if(nodenum==0) nodenum=256;
infile.read(buffer,1);
rearnum=(unsigned char)*buffer;
infile.read((char*)&codelen,4);
ht=new HTNode[2*nodenum-1];
hcd=new HCode[nodenum];
for(h=0;h<nodenum;h++)
{
infile.read(&ht[h].data,1);
infile.read((char*)&ht[h].weight,4);
}
//////构造哈夫曼树///////
HTCreat(ht,nodenum);
//////构造哈夫曼编码/////
HCCreat(ht,hcd,nodenum);
///////////////////////////////////////////////
///////////////////////解压并输出解压文件////////////////////////
char *buffertmp=new char;
int bin[8],j=0,i=0;
int coderead=0; //记录以度的长度,用于判断何时达到文件最后一字节(用codelen比较)
int readlen=0;
int child=0;
int last=2*nodenum-2; //解压时记录上次指示器的位置
child=last;
unsigned char outp;
h=0;
do
{
infile.read(buffer,bufferlen);
readlen=infile.gcount();
for(j=0;j<readlen;j++)
{
coderead++;
outp=buffer[j];
Dec2Bin(outp,bin);
if(coderead==codelen) //达到文件尾
{
for(i=0;i<=8-rearnum;i++)
{
if(ht[child].lchild==-1 && ht[child].rchild==-1)
{
outbuffer[h]=ht[child].data;
h++;
if(h==bufferlen) {outfile.write(outbuffer,bufferlen);h=0;}
last=2*nodenum-2;
if(i==8-rearnum)
{
if(h!=0) outfile.write(outbuffer,h);
child=last;
break;
}
else i--;
}
else if(i!=8)
{ if(bin[i]==0) last=ht[child].lchild;
else if(bin[i]==1) last=ht[child].rchild;
}
child=last;
}
}
else //没达到文件尾
{
for(i=0;i<=8;i++)
{
if(ht[child].lchild==-1 && ht[child].rchild==-1)
{
outbuffer[h]=ht[child].data;
h++;
if(h==bufferlen)
{
outfile.write(outbuffer,bufferlen);
h=0;
}
last=2*nodenum-2;
if(i==8)
{
child=last;
break;
}
else i--;
}
else if(i!=8)
{ if(bin[i]==0) last=ht[child].lchild;
else if(bin[i]==1) last=ht[child].rchild;
}
child=last;
}
}
}
}
while(readlen==bufferlen);
infile.close();
outfile.close();
}
string function::Compression(string fileadd)
{
int i;
for(i=0;i<fileadd.length();i++)
if(fileadd[i]=='\\') fileadd[i]='/';
string fileadd2;
fileadd2=fileadd+".huk";
InitFromFile(fileadd); //从文件中初始化哈夫曼树
HTCreat(ht,nodenum); //构造哈夫曼树
HCCreat(ht,hcd,nodenum); //构造哈夫曼编码
ConvertFile(hcd,fileadd,fileadd2); //压缩并写入文件
clean();
return fileadd2;
}
string function::Decompression(string fileadd2)
{
int i;
for(i=0;i<fileadd2.length();i++)
if(fileadd2[i]=='\\') fileadd2[i]='/';
string fileclass;
string fileadd3;
for(i=fileadd2.length()-5;fileadd2[i]!='.' && i>0;i--) fileclass.insert(0,fileadd2.substr(i,1));
if(i!=0) fileadd3=fileadd2.substr(0,i)+"new"+'.'+fileclass;
else fileadd3=fileadd2.substr(0,fileadd2.length()-4)+"new";
DecompressionFile(fileadd2,fileadd3);
clean();
return fileadd3;
}
void CHaffmanDlg::OnCompress()
{
// TODO: Add your control notification handler code here
if(m_Addr=="")
{
MessageBox("请选择路径!","错误",MB_ICONERROR | MB_OK);
}
else
{
function func;
func.Compression(m_Address);
MessageBox("压缩成功,感谢您的使用!!","成功!");
}
}
void CHaffmanDlg::OnUncompress()
{
// TODO: Add your control notification handler code here
if(m_Addr1=="")
{
MessageBox("请选择路径!","错误",MB_ICONERROR | MB_OK);
}
else
{
function func;
func.Decompression(m_Address);
MessageBox("解压成功,感谢您的使用!!","成功!");
}
}
void CHaffmanDlg::OnFileOpen()
{
// TODO: Add your control notification handler code here
CFileDialog fileDlg(TRUE);
fileDlg.m_ofn.lpstrTitle="我的文件打开对话框";
fileDlg.DoModal();
m_Addr=fileDlg.GetPathName();
m_Address=m_Addr;
UpdateData(FALSE);
}
void CHaffmanDlg::OnFileOpen1()
{
// TODO: Add your control notification handler code here
CFileDialog fileDlg(TRUE);
fileDlg.m_ofn.lpstrTitle="我的文件打开对话框";
fileDlg.DoModal();
m_Addr1=fileDlg.GetPathName();
m_Address=m_Addr1;
UpdateData(FALSE);
}
void CHaffmanDlg::OnChangeAddr()
{
// TODO: If this is a RICHEDIT control, the control will not
// send this notification unless you override the CDialog::OnInitDialog()
// function and call CRichEditCtrl().SetEventMask()
// with the ENM_CHANGE flag ORed into the mask.
// TODO: Add your control notification handler code here
}
void CHaffmanDlg::OnChangeAddr1()
{
// TODO: If this is a RICHEDIT control, the control will not
// send this notification unless you override the CDialog::OnInitDialog()
// function and call CRichEditCtrl().SetEventMask()
// with the ENM_CHANGE flag ORed into the mask.
// TODO: Add your control notification handler code here
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -