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