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

📄 text.cpp

📁 提供文本的无损压缩功能
💻 CPP
字号:
#include "stdafx.h" 
#include "Text.h"
#include "BinaryTree.h"
#include "huffman.h"

 
#define  OFFSET  1024
Text::Text()
{
	 
	 BOOL openfile=0;
	 NUM=256;
	 Number=0;
	 for(int i=0;i<NUM;i++)
		 frequency[i]=0;
	  chpath=new char*[256];
	 t=new BYTE[256]; 
}
 
Text::~Text()
{
} 
 
 BinaryTree<int>Text :: HuffmanTree( int n)
{ 	
   Huffman  *w = new Huffman   [n+1];
   BinaryTree<int> z, zero;
   for (int i = 1; i <= n; i++)
   {
	  z.MakeTree(t[i-1], zero, zero);
	  w[i].weight = frequency[t [i-1]];
      w[i].tree = z;

    }

   // make array into a min heap
   MinHeap<Huffman> H(1);
   H.Initialize(w,n,n);

   // repeatedly combine trees from heap
   Huffman  x, y;
   for (int i = 1; i < n; i++)
   {
      H.DeleteMin(x);
      H.DeleteMin(y);
      z.MakeTree(0, x.tree, y.tree);
      x.weight += y.weight; x.tree = z;
      H.Insert(x);
   }
   H.DeleteMin(x); // final tree
   H.Deactivate();
   delete [] w;
   return x.tree;
}
void Text::ReadAllFile(CString filename1,CString filename2)
{
	const int flag=1;
	UINT  count;
	int number=0;

	BYTE bt[OFFSET];

	if(readfile.Open((LPCTSTR)filename1, CFile::modeRead ,NULL))
	{
	    while(flag)
	    {
	       count=readfile.Read(bt,OFFSET);
		   for(UINT i=0;i<count;i++)
	       {
             frequency[bt[i]]++;//统计频率
	       }
		   if(count!=1024)
			  break;
	 
	    }
		int k=0;
		for(int i=0;i<256;i++)
		{
			if(frequency[i])
			{
				t[k++]=i;//获取非零频率所在数组的下标
				Number++;//非零下标数目
			}		
		}	
		for(int k=0,j=0;k<NUM;k++)
		{
			if(frequency[k])
			{
				str[j].frequency=frequency[k];
				str[j++].code=k;
			}
		}
	}
	Huffman  huffman;
	BinaryTree<int>  Btr;
	BYTE  H;
    Btr= HuffmanTree( Number);//构建霍夫曼树
	H=(BYTE) Btr.Height();//获取霍夫曼树高度,即编码数组的长度,以分配空间
	 for(int i=0;i<=256;i++)
		 chpath[i]=new char[H]; 
	 Btr.OuthuffmanTreePath(chpath,Number);//获取霍夫曼编码

	 writefile.Open((LPCTSTR)filename2,CFile::modeWrite ,NULL); 
	 writefile.SeekToBegin();
     writefile.Write(&H,sizeof(BYTE));
	 writefile.Write(&Number,sizeof(BYTE));
	 //writefile.Write(&str,sizeof(STR_)*(Number+1));

	// writefile.Write(&Number,sizeof(BYTE));

	for(int i=0;i<=Number;i++)
	{
	     writefile.Write(&t[i],sizeof(BYTE)); 
		 writefile.Write(&frequency[t[i]],sizeof(UINT)); 
	}

 
	 UINT    WriteByteCount=OFFSET;
	 BYTE    b[OFFSET];
	 WORD    Bitflag=0;
	 DWORD   Bit=0 ;
	 int     flag1=0;
	 size_t  l;
	 readfile.SeekToBegin();
	 while(WriteByteCount==OFFSET)
	 {
		 WriteByteCount=readfile.Read(b,OFFSET);
		 for(UINT i=0;i<WriteByteCount;i++)
		 {
              l=strlen(chpath[b[i]]);//huofuman编码,形如1010110
			 for(size_t k=0;k< l;k++)
			 {
				 if(Bitflag==32)
				 {	
					 writefile.Write(&Bit,sizeof(DWORD));//够三十二位后写文件
					 Bitflag=0;
					 Bit =0;
				 }
				 Bit=Bit<<1;//转换成DWORD
				 Bitflag++;
				 if(chpath[b[i]][k]=='1')
					 Bit =Bit|1;
          
			 }
		 }  
    }
	 if(Bitflag!=32)//不够32位,左移
		 {
			 Bit =Bit<<(32-Bitflag);
			 writefile.Write(&Bit,sizeof(DWORD));
		 }
 }
void Text::OpenPressFile(CString filename1, CString filename2)
 {
 
	const  int flag=1;
	int    Flag=0;
	BYTE   write[256];//写文件是所用的统计数组
	DWORD  rd[OFFSET/4];
    BYTE   n,m;
	BinaryTree<int>  Btr1,Btr2,Ltree,Rtree;
    
	  //pressfile.Read(&n,sizeof(BYTE));
	UINT  ReadByteCount=OFFSET;

	if(pressfile.Open(filename1,CFile::modeRead,NULL))
	{
		 
			pressfile.SeekToBegin();
			pressfile.Read(&n,sizeof(BYTE));
			pressfile.Read(&m,sizeof(BYTE));
		 
		 
	}
	for(int i=0;i<=m;i++)
	{
		pressfile.Read(&t[i],sizeof(BYTE));
		pressfile.Read(&frequency[t[i]],sizeof(UINT));
	}
	Huffman  huffman;
	Btr1=Btr2=HuffmanTree(m);//重构霍夫曼树
	presstofile.Open((LPCTSTR)filename2, CFile::modeWrite,NULL); 
	 
	DWORD  dwordflg=0;
	while(ReadByteCount==OFFSET)
	{
		ReadByteCount=pressfile.Read(rd,OFFSET);
		if(ReadByteCount==OFFSET)
		{
			for(UINT i=0;i<ReadByteCount/4;i++)
			 {
			 
				for(int k=31;k>=0;k--)
				{
                   dwordflg=rd[i];//读出来的数据用DWORD类型的数组存
				   dwordflg= dwordflg>>31;
				   rd[i]=  rd[i]<<1;
				   Btr1.BreakTree(Ltree,Rtree);
				   if(dwordflg)
					   Btr1=Rtree;
				   else Btr1=Ltree;
				   // Btr1=dwordflg?Rtree:Ltree;
				
				if(!Btr1.huffmanTreeLeaves())//判断节点是否是叶子节点
				{
					 
					write[Flag]=Btr1.Data();
					Flag++;
                    Btr1=Btr2;
					if(Flag==256)
					{
						presstofile.Write(&write,sizeof(write));
                        Btr1=Btr2;
				   	    Flag=0;
					}
				 }
			  }
			}
		}
		else
		{
			for(UINT i=0;i<ReadByteCount/4;i++)
			{
				for(int k=31;k>=0;k--)
				{
                   dwordflg=rd[i]; 
				   dwordflg=dwordflg>>31;
				   rd[i]=rd[i]<<1;//左移一位,改变rd[]里的值,直到零
				   Btr1.BreakTree(Ltree,Rtree);
				   /*if(dwordflg)
					   Btr1=Rtree;
				   else Btr1=Ltree;*/
				   Btr1=dwordflg?Rtree:Ltree;//用原树的左右子树更新现在的树,dwordflg是零取左树,1取右树
				   if(!Btr1.huffmanTreeLeaves())//判断节点是否是叶子节点
				   {
					   if(i==(ReadByteCount/4-1)&&rd[i]==0)
					   {
						 presstofile.Write(&write,Flag);
						 return;
					   }
					   write[Flag]=Btr1.Data();
					  // Flag++;
                       Btr1=Btr2;
					    Flag++;
					   if(Flag==256)
					   {
						  presstofile.Write(&write,sizeof(write));
                          Btr1=Btr2;
						  Flag=0;
					   }
				   }				   
				}	 
			}
		}
	}	 
}

⌨️ 快捷键说明

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