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

📄 haffmandlg.cpp

📁 哈夫曼压缩解压缩的编码。很好的思路和方法。希望能够对大家有所帮助。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
            }
            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 + -