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

📄 ve-27.tmp

📁 自己写的huffman压缩 自己写的huffman压缩 自己写的huffman压缩
💻 TMP
字号:
#include "StdAfx.h"
#include "WinZip.h"
#define BLOCKSIZE 1000
#define WRITEBLOCKSIZE 1000
#define WORDSIZE 256
CWinZip::CWinZip(void)
: m_Path(_T(""))
, m_dePath(_T(""))
{

	m_CountedMem=new int[WORDSIZE];
	for(UINT i=0;i<WORDSIZE;i++)
	{
		m_CountedMem[i]=0;
	}
}CWinZip::~CWinZip(void)
{

}
bool CWinZip::CountWeight(const UINT& size,unsigned char*pbuf)
{
	for(UINT i=0;i<size;i++)
	{
		m_CountedMem[(unsigned char)pbuf[i]]++;
	}
	return true;
}

Huffman* CWinZip::Min(Huffman *huff,int num,bool*reached,bool& Empty)
{
	Empty=true;
	int j=0;
	Huffman *temp=new Huffman;
	for(int i=0;i<num;i++)
	{
		if(!reached[i]&&*temp>huff[i])
		{
			j=i;
			*temp=huff[i];		
			Empty=false;
			if(*temp==1)
				break;
		}
	}
	reached[j]=true;
	return temp;
}
void  CWinZip::Insert (const Huffman &mem,Huffman *huff,int num,bool*reached)
{
	for(int i=0;i<num;i++)
	{
		if(reached[i])
		{
			huff[i]=mem;
			reached[i]=false;
			return;
		}
	} 
}
bool CWinZip::GetPath(const bool& in,CString& path,CString &n)//0为取得输出路径,1为取得输入路径
{
	HRESULT hResult;
	CFileDialog filedlg(true);
	hResult=(int)filedlg.DoModal();
	if(FAILED(hResult))
		return false;
	n=filedlg.GetFileExt();
	if(in)
	{
		m_Path=filedlg.GetPathName();
		path=m_Path;
	}
	else
	{
		m_dePath=filedlg.GetPathName();
		path=m_dePath;
	}
	return true;
}
bool CWinZip::Zip()
{
	m_ProgCtrl->SetRange(0,100);
	////////////////////////////////////////////////////////////
	//读文件
	CFile *fileFrom;                                              //源文件
	fileFrom=new CFile(m_Path,CFile::modeReadWrite);
	unsigned char *pbuf=new unsigned char[BLOCKSIZE];
	int nBytesRead;
	do{
		nBytesRead= fileFrom->Read(pbuf, BLOCKSIZE );				//读文件
		CountWeight(nBytesRead,pbuf);                               //统计出现频率
	}while(nBytesRead==BLOCKSIZE);   //到达文件尾
	m_ProgCtrl->OffsetPos(10);
	////////////////////////////////////////////////
	//统计频率不为零的元素 并创建huffman叶节点
	Huffman huff[WORDSIZE];                                     //存放huffman树的叶节点的数组
	int huffArraysize=0;                                        //数组大小
	for(UINT i=0;i<WORDSIZE;i++)                                //创建huffman树的叶节点 频率不为零的才创建
	{
		if(m_CountedMem[i])
		{
			Huffman *h=new Huffman(m_CountedMem[i],i,NULL,NULL);
			huff[huffArraysize]=*h; 
			huffArraysize++;
		}
	}
	m_ProgCtrl->OffsetPos(10);
	///////////////////////////////////////////////////////////////
	//创建huffman树
	/*MinHeap<Huffman> H(1);
	H.Initialize(*huff,huffArraysize,WORDSIZE);*/
	Huffman* x, *y,*z;                                             //存入权值最小的那两个节点
	bool Empty;                                                 //huffman树的叶节点是否已经全部插入huffman树
	bool *ReachedCode=new bool[huffArraysize];                  //是否已插入的标记数组
	for(int i=0;i<huffArraysize;i++)
		ReachedCode[i]=false;
	while(true)
	{
		x=Min(huff,huffArraysize,ReachedCode,Empty);
		y=Min(huff,huffArraysize,ReachedCode,Empty);
		z=new Huffman(x->count+y->count,-1,x,y);
		if(Empty)
			break;
		Insert(*z,huff,huffArraysize,ReachedCode);
	}
	m_ProgCtrl->OffsetPos(10);
	delete []ReachedCode;
	////////////////////////////////////////////////////////////////////
	//编码
	m_huffmanCodeWide=new int[huffArraysize];
	m_AllCodeArrary=new byte[huffArraysize*2];                       //huffman树统计后二进制编码存放的数组
	m_CountedCode=new unsigned char[huffArraysize];
	m_AllCode=new int[WORDSIZE];
	m_MemSign=new int[huffArraysize]; 
	int CodeNo=0,ArrayNo=0;
	for(int i=0;i<huffArraysize;i++)
	{
		m_huffmanCodeWide[i]=0;
		m_CountedCode[i]=0;
		m_MemSign[i]=0;
	}
	m_ProgCtrl->OffsetPos(10);
	for(int i=0;i<huffArraysize*4;i++)
		m_AllCodeArrary[i]=0;
	PreOrder(x,CodeNo,ArrayNo,huffArraysize);                               //通过huffman树统计出编码
	m_ProgCtrl->OffsetPos(10);
	/////////////////////////////////////////////////////////////////////////////
	//再读文件并写文件
	fileFrom->SeekToBegin();
	CFile *fileTo;                                               //目标文件
	fileTo=new CFile(m_dePath,CFile::modeCreate|CFile::typeBinary|CFile::modeWrite);//创建文件
	int lenth=ArrayNo+(m_huffmanCodeWide[huffArraysize-1]-1)/8;
	fileTo->Write(&huffArraysize,4);
	fileTo->Write(&ArrayNo,4);
	//fileTo->Write(&lenth,4);
	fileTo->Write(m_CountedCode,huffArraysize);
	fileTo->Write(m_huffmanCodeWide,huffArraysize*4);
	fileTo->Write(m_AllCodeArrary,ArrayNo+1);
	byte *b_pbuf=new byte[WRITEBLOCKSIZE];
	for(int i=0;i<WRITEBLOCKSIZE;i++)
	b_pbuf[i]=0;
	m_ProgCtrl->OffsetPos(20);
	nBytesRead=BLOCKSIZE;
	unsigned long int bufferPt;
	do{
		int temp;
		bufferPt=1;
		while((bufferPt<WRITEBLOCKSIZE*8-8)&&nBytesRead==BLOCKSIZE)
		{
			nBytesRead= fileFrom->Read(pbuf,BLOCKSIZE );//每次读blocksize大小
			temp=nBytesRead;
			Translate(pbuf,b_pbuf,temp,bufferPt);//放入byte型的数组b_pbuf,直到放满
		}
		fileFrom->Seek(-temp,CFile::current);
		fileTo->Write(b_pbuf,WRITEBLOCKSIZE);//将B_pbuf的所有元素写入磁盘
	}while(nBytesRead==BLOCKSIZE);
	m_ProgCtrl->OffsetPos(20);
	fileFrom->Close();
	fileTo->Close();
	delete []m_MemSign;
	//delete []m_AllCode;
	delete []m_CountedCode;
	delete []m_huffmanCodeWide;
//	delete []m_AllCodeArrary;
	delete []pbuf;
	delete fileFrom;
//	delete fileTo;
	m_ProgCtrl->OffsetPos(10);
	return true;
}

bool CWinZip::PreOrder(Huffman *root,int& CodeNo,int& ArrayNo,const int& huffArraysize)
{
	if(root->code==-1)
	{
		if (!(m_huffmanCodeWide[CodeNo]%8)&&(m_huffmanCodeWide[CodeNo]!=0))
			ArrayNo++;
		m_AllCodeArrary[ArrayNo]<<=1;
		m_huffmanCodeWide[CodeNo]++;
		if(PreOrder(root->left,CodeNo,ArrayNo,huffArraysize))
			return 1;

		//ArrayNo=k+(i-1)/8+1;
		if(!m_huffmanCodeWide[CodeNo])
		{
			int i=m_huffmanCodeWide[CodeNo-1],j=m_MemSign[CodeNo],k=m_MemSign[CodeNo-1];
			while(i>0)
			{
				ArrayNo++;
				m_AllCodeArrary[j++]=m_AllCodeArrary[k++];
				i-=8;
			}
			m_huffmanCodeWide[CodeNo]=m_huffmanCodeWide[CodeNo-1];
		}
		
		m_huffmanCodeWide[CodeNo]--;
		m_AllCodeArrary[ArrayNo]=m_AllCodeArrary[ArrayNo]>>1;
         if(!(m_huffmanCodeWide[CodeNo]%8)&&m_huffmanCodeWide[CodeNo])
			ArrayNo--;
		//m_AllCodeArrary[ArrayNo]=m_AllCodeArrary[ArrayNo]>>1;
		if (!(m_huffmanCodeWide[CodeNo]%8)&&(m_huffmanCodeWide[CodeNo]!=0))
			ArrayNo++;
		m_AllCodeArrary[ArrayNo]=m_AllCodeArrary[ArrayNo]<<1|1;
		m_huffmanCodeWide[CodeNo]++;
		if(PreOrder(root->right,CodeNo,ArrayNo,huffArraysize))
			return 1;
		
		if(!m_huffmanCodeWide[CodeNo]){
			
			int	i=m_huffmanCodeWide[CodeNo-1],j=m_MemSign[CodeNo],k=m_MemSign[CodeNo-1];
			//ArrayNo=k+(i-1)/8+1;
			while(i>0)
			{
				ArrayNo++;
				m_AllCodeArrary[j++]=m_AllCodeArrary[k++];
				i-=8;
			}

			m_huffmanCodeWide[CodeNo]=m_huffmanCodeWide[CodeNo-1];
			//m_AllCodeArrary[ArrayNo]=m_AllCodeArrary[ArrayNo-1];
		}
		m_huffmanCodeWide[CodeNo]--;
		m_AllCodeArrary[ArrayNo]=m_AllCodeArrary[ArrayNo]>>1;
		if(!(m_huffmanCodeWide[CodeNo]%8)&&m_huffmanCodeWide[CodeNo])
			ArrayNo--;
	}
	else if(CodeNo<huffArraysize)
	{
		m_CountedCode[CodeNo]=root->code;
		m_AllCode[root->code]=CodeNo;
		//ArrayNo++;
		CodeNo++;
		if(CodeNo<huffArraysize)
		{
			m_MemSign[CodeNo]=m_MemSign[CodeNo-1]+(m_huffmanCodeWide[CodeNo-1]-1)/8+1;
			return 0;
		}
		else
			return 1; 
	}
	return 0;
}
void CWinZip::Translate(unsigned char* from,byte*to,int& SourceSize,unsigned long int& ArraySize)
{	//int offset=m_huffmanCodeWide[m_AllCode[from[i]]];
	CStake sk;
	int offset,j=(ArraySize-1)/8;
	for(int i=0;i<SourceSize;i++)
	{
		//ArrayNo=ArraySize/8;
		int m=m_huffmanCodeWide[m_AllCode[from[i]]];
 	    int n=m_AllCode[from[i]];
		if(m>8)
				offset=7;
		else
				offset=m-1;
		for(;m>0;m--)
		{
			sk.Add((m_AllCodeArrary[n]&(1<<offset))>>offset);
			offset--;
			if(offset==-1)
				n++;
			if(sk.Full())
			{
			to[j]=sk.Copy();
			j++;
			}
		}
		ArraySize+=m_huffmanCodeWide[m_AllCode[from[i]]];
		if(ArraySize>8*WRITEBLOCKSIZE)
		{
			to[j-1]=to[j-1]<<(8-m_huffmanCodeWide[m_AllCode[from[i]]]%8);
			ArraySize-=m_huffmanCodeWide[m_AllCode[from[i]]];
			SourceSize=SourceSize-i;
			break;
		}
	}
}
bool CWinZip::BuildTree(int& CodeSize,int& AsciiSize,Huffman *&x)
{
	x=new Huffman;
	Huffman *y=x;
	int m=0,offset;
	int n,BitSign;
	for(int i=0;i<AsciiSize;i++)
	{
		x=y;
		BitSign=0;
		if(m_huffmanCodeWide[i]-BitSign<=7)
		offset=m_huffmanCodeWide[i]-BitSign-1;
		else
		offset=7;
		
		while(true)
		{
			n=(m_AllCodeArrary[m]&(1<<offset))>>offset;
			if(n==0)
			{
				if(!x->left)
					x->left=new Huffman;
				x=x->left;
			}
			if(n==1)
			{
				if(!x->right)
					x->right=new Huffman;
				x=x->right;
			}
			if(BitSign<m_huffmanCodeWide[i])
			{
				BitSign++;
				offset--;
			}
			if(BitSign>=m_huffmanCodeWide[i])
			{
				x->code=m_CountedCode[i];
				x->count=1;
				m++;
				break;
			}
			if(offset==-1)
			{
				m++;
				if(m_huffmanCodeWide[i]-BitSign<=8)
				offset=m_huffmanCodeWide[i]-BitSign-1;
				else
				offset=7;
			}
		}
	}
	x=y;
	return 1;
}
bool CWinZip::reversion(byte* Code,unsigned char*& Ascii,int& num,Huffman* x)
{
	Huffman* huffTmp=x;
   Ascii=new unsigned char[BLOCKSIZE];
   int cusor,i=num,offset=7,j=0;
   while(j<BLOCKSIZE&&i<WRITEBLOCKSIZE)
   {
	   huffTmp=x;
	   while(true)
	   {
		   cusor=(Code[i]&(1<<offset))>>offset;
		   offset--;
		   if(cusor==0)
			   huffTmp=huffTmp->left;
		   if(cusor==1)
			   huffTmp=huffTmp->right;
		   if(huffTmp->count==1)
		   {
			   Ascii[j]=huffTmp->code;
			   j++;
			   break;
		   }
		   if(offset==-1)
		   {
			   offset=7;
			   i++;
		       if(i>WRITEBLOCKSIZE)
				   break;
		   }
	   }
   }
   num=i+1;
    return 1;
}
bool CWinZip::ReZip()
{
	//读文件
	CFile *fileFrom;                                              //源文件
	fileFrom=new CFile(m_Path,CFile::typeBinary|CFile::modeRead);
	int huffArraysize,lenth,ArrayNo;
	fileFrom->Read(&huffArraysize,4);
	fileFrom->Read(&ArrayNo,4);
	//fileFrom->Read(&lenth,4);
	m_huffmanCodeWide=new int[huffArraysize];
	m_AllCodeArrary=new byte[ArrayNo+1];                               //huffman树统计后二进制编码存放的数组
	m_CountedCode=new unsigned char[huffArraysize];
	m_AllCode=new int[WORDSIZE]; 
	m_MemSign=new int[huffArraysize];
	fileFrom->Read(m_CountedCode,huffArraysize);
	fileFrom->Read(m_huffmanCodeWide,huffArraysize*4);
	fileFrom->Read(m_AllCodeArrary,ArrayNo+1);
	m_MemSign[0]=0;
	for(int i=1;i<huffArraysize;i++)
		m_MemSign[i]=m_MemSign[i-1]+(m_huffmanCodeWide[i-1]-1)/8+1;
	Huffman *x;
  	BuildTree(lenth,huffArraysize,x);
	 byte* pbuf=new byte[WRITEBLOCKSIZE];				
	 byte* wbuf=new byte[BLOCKSIZE];
	 unsigned char* Ascii;
	 UINT nBytesRead;
	CFile *fileTo=new CFile(m_dePath,CFile::modeCreate|CFile::modeWrite);
	do{
		nBytesRead=fileFrom->Read(pbuf,WRITEBLOCKSIZE);
		int num=0;
		while(num<BLOCKSIZE)
		{
		  reversion(pbuf,Ascii,num,x);
	      fileTo->Write(Ascii,num);
		}
	}while(nBytesRead==WRITEBLOCKSIZE);
	fileTo->Close();
	fileFrom->Close();
	return 1;
}

⌨️ 快捷键说明

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