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

📄 compress.c

📁 哈夫曼压缩程序
💻 C
字号:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<windows.h>
#include<direct.h>

#include"N_error.h"
#include"tree.h"
#include"compress.h"
#include"binary.h"
#include"file.h"

//////////*size of file////////////////////////////////////////////////////////////////////

float IPUTFILESIZETOAL = 0;
/*如果申请空间根据用户反映循环的申请空间*////////////////////////////////////////////////////////////
void *CallSpace(unsigned int size)
{
	void *A = 0;
	while(  ( A = malloc(size) ) == NULL )
	{
		if( !ASK("Not enough memory now!Do you want to close some tasks and retry?(Y/N)") )
			break;
	};
	return A;
}


////////////////////////////////////////////////////////////////////

float SizeHelp(node_p root,int high)
{
	if( IsLeaf(root))
	{	
		return high*(float)GetWeight(root) ;
	}
	else 
	{
		float L,R;
		high++;
		L = SizeHelp( GetLeft(root),high );
		R =  SizeHelp( GetRight(root),high );
		high--;
		return ( L + R);		
	}
	
}

unsigned int SizeOfOutFile(node_p root)
{ //when calculate the out size the end of codes out put a extranal char and a extranal information char so we add 2 to outfile size;
	unsigned int r = 0;
	r = (int)SizeHelp(root,0)/8+2;
	 return r;
}
/////////////////////////////////////////////////////////////////////////////////////////
int TranslateAndSto(FILE *fsource,FILE *fgoal,node_p const codetree,weight_t *KeyArray)
{
	int help,ch;
	node_p p = codetree;
	unsigned char *const cwp = (unsigned char*)&help , *const positionp = (unsigned char*)&help+1;

	*cwp = 0;
	*positionp = 7;
	while( (ch = ReadC(fsource)) != EOF)
	{
		if( !codetree)
		{
			N_ERROR("at TranslateAndSto the codetree is empty codetree !");
			exit(0);
		}
		p = codetree;
		while( !IsLeaf(p) )
		{
			if( KeyArray[ch] < GetKey(p) )
			{
				p = GetLeft(p);
				WriteBitToC(cwp,0,*positionp);
                if( *positionp )
				{
					(*positionp)--;
				}
				else
				{
					WriteFullCToFile( 1,cwp,fgoal);
					*positionp = 7;
				}
			}
			else
			{
				p = GetRight(p);
				WriteBitToC(cwp,1,*positionp);
                if( *positionp )
				{
					(*positionp)--;
				}
				else
				{
					WriteFullCToFile( 1,cwp,fgoal);
					*positionp = 7;
				}
			}
		}

	}
	if(*positionp != 7)	WriteFullCToFile( 1,cwp,fgoal);//write the last char to file (may be not a full usefull char;)
   return *positionp+1;//return how many bits of the end is rubbsh;
}

//////////////////////////////////////////////////////////////////////////////////////////
int GiveFormHead(FILE *fp)
{
	 if( WriteStrToF("this is a good compress software!",fp))
		 return 1;;
	 return 0;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
 int CompressAFile(FILE *fpInFile,FILE *fpOutFile)
{
//	char BitsOfRubbish;
	unsigned long int InFileSize,OutFileSize;
	weight_t A[256] = {0};
	node_p root;
	
	InFileSize = Statist(A,fpInFile);
	IPUTFILESIZETOAL += InFileSize;

	if(fseek(fpInFile,0,0) != 0)
	{
		N_ERROR("can not replace the pointor of source file");
		return 0;
	}
	root = ConstructTree(A);

	//if root is 0 then thie file is empty!
	if( !root)
	{
		if(!WriteC( 0,fpOutFile,"At function compress Write file error"))
			return 0;
		if(!WriteC(0,fpOutFile,"At function compress Write file error"))
			return 0;
		WriteLIntToF(0,fpOutFile);
	
		return (2 + 4); 
	}

	//****when the file has more then a codes do it by use the tree***
	else if( !IsLeaf(root) )
		{
			TreeSto(root,fpOutFile);

			OutFileSize = SizeOfOutFile(root);
		
			WriteLIntToF(InFileSize,fpOutFile);
			TranslateAndSto(fpInFile,fpOutFile,root,A);

			OutFileSize += LeafNumber(root)*9/8+1;
			FreeTree(root);	
			return OutFileSize; 

		}
		///********if the input file only has one code we just store how many numbers of that code the file has***********
		else 
		{
			if(!WriteC( GetLabel(root),fpOutFile,"At function compress Write file error"))
				return 0;
			if(!WriteC(GetLabel(root),fpOutFile,"At function compress Write file error"))
				return 0;
			WriteLIntToF(InFileSize,fpOutFile);
		
			FreeTree(root);	
			return (2 + 4); 
		}
}

long int Compress(const char *InFilePath,const f_name_t InFileNames,const char *OutFilePath,const char *OutFileName)
{
	char temp[MAX_PATH] = {0},temp1[MAX_PATH] = {0},*inname = 0;//use to ensure that the space of file name string is enough;  
	char errormsg[256] = {0};
	long int OutSize = 0;
	FILE *fps,*fpg;
	f_name_node_p namep = InFileNames.head;
	
	errormsg[0] = 0;
	strcat(errormsg,"at function Compress Can't create file ");
	strcat(errormsg,OutFileName);
///copy the file path to the enough space string and link the out file name to the end ;
	OutFilePath = strcpy(temp,OutFilePath);
	OutFileName = LinkPath_Name(OutFilePath,OutFileName);

	//open the out file;
	if( !(fpg = OpenF(OutFileName,"wb",errormsg)))
		return 0;
	GiveFormHead(fpg);
    
	while(namep)
	{
///get the full path and name of input file F_N_GetName(namep) store it to temp and made inneme point to it;
		inname = strcpy(temp1,InFilePath);
		inname = LinkPath_Name(inname,F_N_GetName(namep));

		errormsg[0] = 0;
		strcat(errormsg,"at function Compress Can't open file ");
		strcat(errormsg,inname);

		if( !(fps = OpenF(inname,"rb",errormsg)))
		{
			if(ASK("do you want to continue?"))
				break;//do nothing;
			else
			{
				fclose(fpg);
				remove(OutFileName);
				return 0;
			}
		}
		if( !WriteStrToF(F_N_GetName(namep),fpg))
		{
			errormsg[0] = 0;
			strcat(errormsg,"at function Compress Can't write the file name to ");
			strcat(errormsg,OutFileName);

			if(ASK(""))//do nothing;
			{
				break;
			}
			else
			{
				fclose(fpg);
				remove(OutFileName);
			}
		}
		CompressAFile(fps,fpg);
		fclose(fps);
	namep = F_N_GoNext(namep);
	}
	OutSize = ftell(fpg);
	fclose(fpg);
	return OutSize;
}
//////////////////////////////////////////////////////////////////////////
void PrintHelp()
{
	printf("This is a free compress software \
\nuse help :\ncompress:\n compress outfilename folder1 folder2 ...\
\n outfilename is the out put file name which will write to the \
\n current work folder ! folder1 folder2 ...are folders while you \
\nwant to compress rember the folders must in the current work path!\
\nthank you for using it !");

}

///////////////////////////////////////////////////////////////////////////////

int main(int argc ,char **argv)
{
	float rate;
	unsigned int OutSize;
	int i = 0;
	f_name_t names = CreateFileName(); 
	char *OutFileName,temp[MAX_PATH] = {0},CurPath[MAX_PATH] = {0};

	if(argc < 3)
	{
		PrintHelp();
		return 1;
	}
	getcwd(CurPath,MAX_PATH);

    
	i = 2;
	while(argv[i])
	{
		AddFileFromFolder(CurPath,argv[i],&names);
		i++;
	}
	OutFileName = argv[1];
	if(OutFileName)
	{
		OutFileName = strcat(temp,OutFileName);
		OutFileName = strcat(OutFileName,".nw");
	}
	else 
	{
		N_ERROR("must input a out file name!");
		exit(0);
	}
/*	AddFileName(&names,"a.txt");
	AddFileName(&names,"a.txt");
	AddFileName(&names,"b.txt");

	OutFileName = "t";
*/
	//get the current work path

	if(OutSize = Compress(CurPath,names,CurPath,OutFileName))
	{
		if(OutSize)rate = OutSize/IPUTFILESIZETOAL;
		printf("Compressed successfully!\nInput Files total Size is %0.0f\nOutput file %s  %d\ncompress rate is %f",IPUTFILESIZETOAL,OutFileName,OutSize,rate);
	}
	else 
		printf("Did not compress \n");
	FreeFileList(&names);

//	Compress("a.txt","b.nb");
}

////////////////////////////////////////////////////////

⌨️ 快捷键说明

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