www.pudn.com > rlezip.rar > rlezip.cpp


#include  
#include  
#include  
#include  
#include  
#include  
 
int g_nCurDirLayer = 0;  //当前正在处理的文件夹所处的层次 
const int ATTR_FILE = 0; 
const int ATTR_DIR =  1; 
FILE * g_fpData;			//压缩时的目标文件 
FILE * g_fpZippedFile;		//解压缩时的目标文件 
 
struct tagFileInfo  
{ 
	char cFileNameLength;	//文件名的长度(使写在文件中的文件信息缩短) 
	char szFileName[256];  //文件名或文件夹名字 
	int nLayer;			   //文件或文件夹所在的层次,根文件夹所处层次为0 
	int nLength;		   //文件压缩后的长度 
	int nAttr;			   //为 ATTR_FILE 代表文件,为 	ATTR_FILE 代表文件夹  
}; 
 
void WriteFileInfo(tagFileInfo & FileInfo) 
{ 
	//将文件信息写入文件 
	int i = 0; 
 
	fwrite( & FileInfo.cFileNameLength,sizeof(char),1,g_fpData); 
	while( FileInfo.szFileName[i]!='\0') 
		fwrite( & FileInfo.szFileName[i++],sizeof(char),1,g_fpData); 
	fwrite( & FileInfo.nLayer,sizeof(int),1,g_fpData); 
	fwrite( & FileInfo.nLength,sizeof(int),1,g_fpData); 
	fwrite( & FileInfo.nAttr,sizeof(int),1,g_fpData); 
} 
 
void CompressFile( char * szFile) 
{ 
	//压缩一个文件 
	tagFileInfo FileInfo; 
	FILE * fpSrc;			//目标文件指针 
	int i,j,k; 
	int c; 
	int power;				//用于计算2^n 
	int CompressTypt[8];	//标示(m个n,还是n) 
	char CompressNum[8];	//字符连续的个数 
	char CompressChar[8];	//字符 
	int nFileEnd;			//在一个压缩单元中,文件结束的位置 
	const int NUM_CHAR = 0; 
	const int ONLY_CHAR = 1; 
	int nCharNum = 1;		//相同字符连续的个数 
	char cCurrentChar = -1;	//纪录上一个字符 
	int nTemp = 0; 
 
	//建立文件信息 
	memset(	CompressTypt,0,sizeof(bool)*8); 
	memset( & FileInfo,0,sizeof(FileInfo)); 
	strcpy( FileInfo.szFileName,szFile); 
	FileInfo.cFileNameLength = (char)strlen( szFile); 
	FileInfo.nLayer = g_nCurDirLayer; 
	FileInfo.nAttr = ATTR_FILE; 
 
	//计算压缩后的文件长度 
	fpSrc = fopen( szFile,"rb"); 
	if (fpSrc == NULL)  //错误处理 
	{ 
		cout<<"The file "< 1) 
					FileInfo.nLength+=2;	//m个n,要写入m n,所以占两字节 
				else 
					FileInfo.nLength++;		//只写入该字符,只占一字节 
				cCurrentChar = c; 
				nCharNum = 1; 
			} 
			if (c == EOF) 
				break;		//到达文件最后,退出循环 
		} 
		if (c == EOF) 
			break; 
	} 
	fclose( fpSrc); 
 
	//将文件信息写入文件 
	WriteFileInfo( FileInfo); 
 
	//将压缩码写入文件 
	//重新打开文件 
	fpSrc = fopen( szFile,"rb");  
	c = fgetc( fpSrc); 
	cCurrentChar = c; 
	nCharNum = 1; 
	while(1)  
	{ 
		memset(CompressTypt,0,8); 
		memset(CompressChar,0,8); 
		memset(CompressNum,0,8); 
		nFileEnd= 9; 
		j=0; 
		//储存一个压缩单元中的信息,并输出至目标文件 
		//一个压缩单元包括: 
		//表示8个标示的一个字节,下面是8个压缩码(m n或n的形式) 
		while(j<8) 
		{ 
			//储存下面8个压缩的信息到内存(包括字符,个数,以及标示) 
			c = fgetc( fpSrc); 
			if (c == cCurrentChar && nCharNum < 255) 
				nCharNum++; 
			else 
			{ 
				if (nCharNum > 1) 
					CompressTypt[j] = NUM_CHAR;		//储存标示 
				else 
					CompressTypt[j] = ONLY_CHAR; 
				CompressNum[j] = nCharNum;		//储存个数 
				CompressChar[j] = cCurrentChar;		//储存字符 
				 
				cCurrentChar = c; 
				nCharNum = 1; 
				j++; 
			} 
			if (j == 8) 
				break;		//一个单元结束,退出循环 
			if (c == EOF) 
			{ 
				nFileEnd = j; 
				break;		//文件结束,退出循环 
			} 
		} 
		//将储存好的8位标示转换成10进制整数,并写在一个字节中 
		nTemp=0; 
		for (j=0; j<8 && j=FileInfo.nLength) 
				break; 
		} 
		if (i>=FileInfo.nLength) 
			break; 
	} 
	fclose( fpAim); 
} 
 
void CompressDir( char * szDir )   
{ 
	//压缩一个文件夹 
	tagFileInfo FileInfo; 
	int i,nLen; 
	memset( & FileInfo,0,sizeof(FileInfo)); 
	nLen = strlen( szDir); 
 
	//不需要绝对路径, 下面4行是抽取单纯的文件夹名字 
	for( i = nLen; i > 0 ;i --) 
		if (szDir[i]== '\\' || szDir[i]=='/') 
			break; 
	if( szDir[i] == '\\' || szDir[i]=='/') 
		i ++; 
	strcpy( FileInfo.szFileName,szDir + i); 
	FileInfo.cFileNameLength = strlen(FileInfo.szFileName); 
	FileInfo.nLayer = g_nCurDirLayer; 
	FileInfo.nAttr = ATTR_DIR; 
	WriteFileInfo(FileInfo); 
	g_nCurDirLayer ++; 
 
	_chdir( szDir );    //当前路径设为该文件夹 
	WIN32_FIND_DATA stFindClientData;		 
	HANDLE hFindClient; 
 
	//找到第一个文件夹即其自身 " . " ,不作处理 
	hFindClient = FindFirstFile( "*.*" , &stFindClientData );     
	if ( hFindClient == INVALID_HANDLE_VALUE )  
	{ 
		return ; 
	} 
	//找到第二个文件夹即其父文件夹 ".. " ,,不作处理 
	FindNextFile( hFindClient , & stFindClientData ); 
 
	//循环查找其它子文件夹和文件 
	while ( FindNextFile( hFindClient,& stFindClientData))  
	{ 
			//如果是子文件夹,则递归调用 CompressDir 进行打包 
			if (FILE_ATTRIBUTE_DIRECTORY == stFindClientData.dwFileAttributes)   
			{ 
	//			g_nCurDirLayer ++; //stFindClientData.cFileName 文件夹的层次比当前文件夹即 szDir 多1  
				CompressDir( stFindClientData.cFileName);   
	//			g_nCurDirLayer --; //处理完stFindClientData.cFileName 文件夹后,层次值要恢复到 szDir 的层次值 
			} 
			else //是文件 
			{ 
				CompressFile( stFindClientData.cFileName);				 
			} 
	} 
	//关闭查找句柄 
	FindClose( hFindClient); 
	//返回父文件夹 
	_chdir( ".." ); 
	g_nCurDirLayer --; 
} 
 
void DeCompressDir() 
{ 
	//解压缩一个文件夹 
	tagFileInfo FileInfo; 
	int nZippedFileSeek; 
	int i; 
 
	while(1) 
	{ 
		nZippedFileSeek = ftell( g_fpZippedFile);	//纪录偏移量 
		//读入文件信息 
		FileInfo.cFileNameLength = fgetc(g_fpZippedFile); 
		if (FileInfo.cFileNameLength == EOF) 
			break; 
		for (i=0; i<(int)FileInfo.cFileNameLength; i++) 
			FileInfo.szFileName[i] = fgetc(g_fpZippedFile); 
		FileInfo.szFileName[i] = '\0'; 
		fread( & FileInfo.nLayer,sizeof(int),1,g_fpZippedFile); 
		fread( & FileInfo.nLength,sizeof(int),1,g_fpZippedFile); 
		fread( & FileInfo.nAttr,sizeof(int),1,g_fpZippedFile); 
		//如果该层次结束,则将文件重新定位到上面储存的偏移量上 
		if (FileInfo.nLayer != g_nCurDirLayer) 
		{ 
			fseek(g_fpZippedFile,nZippedFileSeek,SEEK_SET); 
			break; 
		} 
		if (FileInfo.nAttr == ATTR_FILE) 
			DeCompressFile( FileInfo);	//解压缩文件 
		if (FileInfo.nAttr == ATTR_DIR) 
		{ 
			g_nCurDirLayer++;		 
			_mkdir(FileInfo.szFileName);	//建立文件夹 
			_chdir(FileInfo.szFileName);	//进入该文件夹 
			DeCompressDir();				//解压缩文件夹(递归) 
			g_nCurDirLayer--; 
			_chdir( ".." );			//返回上一级文件夹 
		} 
	} 
} 
 
void CompressCurDir(char * szName) 
{ 
	WIN32_FIND_DATA stFindClientData;		 
	HANDLE hFindClient; 
 
	//找到第一个文件夹即其自身 " . " ,不作处理 
	hFindClient = FindFirstFile( "*.*" , &stFindClientData );     
	if ( hFindClient == INVALID_HANDLE_VALUE ) 
		return ; 
 
	//找到第二个文件夹即其父文件夹 ".. " ,,不作处理 
	FindNextFile( hFindClient , & stFindClientData ); 
 
	while ( FindNextFile( hFindClient,& stFindClientData))  
	{ 
		if (FILE_ATTRIBUTE_DIRECTORY == stFindClientData.dwFileAttributes)  {} 
		else{ 
			if (strcmp(stFindClientData.cFileName,"rlezip.exe") != 0 
				&& strcmp(stFindClientData.cFileName,szName) != 0 ) 
				CompressFile( stFindClientData.cFileName); 
		} 
	} 
	//关闭查找句柄 
	FindClose( hFindClient); 
} 
 
void main( int argc ,char * argv[]) 
{ 
	int i,j; 
	int nDirLength; 
	int nIsFile; 
	if( argc == 1 ) 
		return; 
	if( strcmp( argv[1],"-e") == 0 )  
	{ 
		g_fpData = fopen( argv[argc-1],"wb"); 
		for (i=2; i