?? rlezip2.cpp
字號:
/*
文件打包和解包程序 by 郭 煒
本程序用法:
rlezip -e dirname filename 將文件夾 dirname 中的所有內容打包到 filename 文件里去
dirname 可以是相對路徑,也可以是絕對路徑
rlezip -x filename 將文件 filename里的所有內容解出來,放到當前目錄下
本程序沒有進行壓縮
解壓函數 DeCompressDir 省略
結果文件 結構如下:
每一個文件和文件夾,在結果文件中都有 一個 tagFileInfo結構與之對應。如果一個 tagFileInfo
代表一個文件,那么在該 tagFileInfo后就緊跟著該文件的內容.
//關鍵函數: FindFirstFile, FindNextFile , _chdir, _mkdir
*/
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <direct.h>
#include <io.h>
#include <fstream.h>
int g_nCurDirLayer = 0; //當前正在處理的文件夾所處的層次
const int ATTR_FILE = 0;
const int ATTR_DIR = 1;
const int BUF_LEN = 1024;
ofstream g_ofData;
struct tagFileInfo {
char szFileName[256]; //文件名或文件夾名字
int nLayer; //文件或文件夾所在的層次,
// 根文件夾所處層次為0 ,
// 如果一個文件夾處于n層,
// 那么該文件夾下的文件就都是 n+1層的
int nLength; //文件壓縮后的長度
int nAttr; //為 ATTR_FILE 代表文件,
//為 ATTR_FILE 代表文件夾
};
void CompressFile( char * szFile)
{
tagFileInfo FileInfo;
ifstream ifSrc;
memset( & FileInfo,0,sizeof(FileInfo));
strcpy( FileInfo.szFileName,szFile);
FileInfo.nLayer = g_nCurDirLayer;
FileInfo.nAttr = ATTR_FILE;
//因為本例子不壓縮,所以 FileInfo.nLength 的值就是源文件長度,
//可以事先得到.否則,就要在壓縮完整個文件后,再回填了
ifSrc.open(szFile,ios::in | ios::binary ); //以二進制只讀方式打開文件
ifSrc.seekg(0,ios::end); //定位讀指針到文件末尾
FileInfo.nLength = ifSrc.tellg(); //獲取讀指針位置,即文件長度
ifSrc.seekg(0,ios::beg); //將文件讀指針設置到文件開頭,以便以后讀取
g_ofData.write( (const char * ) & FileInfo,sizeof( FileInfo));
char * pBuf = new char[BUF_LEN];
int nReadedLen ;
do {
ifSrc.read( pBuf,BUF_LEN);
nReadedLen = ifSrc.gcount(); //獲取上次讀操作讀取的字節數
g_ofData.write ( pBuf,nReadedLen);
} while( nReadedLen > 0 ); //如果文件都讀完,無法再讀了,那么nReadedLen 就不會是正數
ifSrc.close();
delete [] pBuf;
}
void CompressDir( char * szDir ) {
tagFileInfo FileInfo;
int i,nLen;
memset( & FileInfo,0,sizeof(FileInfo));
nLen = strlen( szDir);
for( i = nLen; szDir[i]!= '\\' && i > 0 ;i --);
if( szDir[i] == '\\')
i ++;
strcpy( FileInfo.szFileName,szDir + i);
FileInfo.nLayer = g_nCurDirLayer;
FileInfo.nAttr = ATTR_DIR;
g_ofData.write( (const char * ) & FileInfo,sizeof(FileInfo));
_chdir( szDir ); //當前路徑設為該文件夾
WIN32_FIND_DATA stFindData;
HANDLE hFindClient;
hFindClient = FindFirstFile( "*.*" , &stFindData );
if ( hFindClient == INVALID_HANDLE_VALUE ) {
return ;
}
do {
if( ! ( strcmp( stFindData.cFileName, "..") == 0 ||
strcmp( stFindData.cFileName, ".") == 0 ) ) { // . 和 .. 代表自己和父目錄,要略過,不予處理
if((FILE_ATTRIBUTE_DIRECTORY &
stFindData.dwFileAttributes) == FILE_ATTRIBUTE_DIRECTORY ) {
g_nCurDirLayer ++; //stFindData.cFileName 文件夾的層次比當前文件夾即 szDir 多1
CompressDir( stFindData.cFileName);
g_nCurDirLayer --; //處理完stFindData.cFileName 文件夾后,層次值要恢復到 szDir 的層次值
}
else{ //是文件
CompressFile( stFindData.cFileName);
}
}
}while( FindNextFile( hFindClient,& stFindData));
//關閉查找句柄
FindClose( hFindClient);
_chdir( ".." ); //返回上層文件夾(即父文件夾)
}
void DeCompressDir( char * szZippedFile)
{
ifstream ifZip;
tagFileInfo FileInfo;
ifZip.open( szZippedFile,ios::in | ios::binary ); // 以二進制只讀方式打開文件
g_nCurDirLayer = 0;
while(ifZip.read( (char *) & FileInfo,sizeof( FileInfo)) ) {
//ifZip.read( (char *) & FileInfo,sizeof( FileInfo));
//int nReadedLen = ifZip.gcount ();
//if( nReadedLen <= 0 )
// break;
//printf( "%s,%d\n",FileInfo.szFileName ,FileInfo.nLayer );
if( FileInfo.nAttr == ATTR_DIR) {
if ( g_nCurDirLayer == FileInfo.nLayer ) {
//正在處理的文件夾層次和 FileInfo.nLayer相等,
//說明 FileInfo 代表的文件夾是正在處理的文件夾
//的子文件夾
_mkdir( FileInfo.szFileName ); //創建文件夾
g_nCurDirLayer ++;
_chdir( FileInfo.szFileName); //改變當前文件夾,即進入剛剛創建的文件夾
}
else if( g_nCurDirLayer > FileInfo.nLayer ) { //正在處理的文件夾層次比 FileInfo.nLayer 大,那么就要回退幾層
for( int i = 0;i < g_nCurDirLayer - FileInfo.nLayer ; i ++ ) {
_chdir ( ".."); //返回上層文件夾(即父文件夾)
}
g_nCurDirLayer = FileInfo.nLayer ;
_mkdir( FileInfo.szFileName );
g_nCurDirLayer ++;
_chdir( FileInfo.szFileName);
}
}
else {
if( g_nCurDirLayer > FileInfo.nLayer + 1 ) { //如果一個文件夾處于n層,那么該文件夾下的文件就都是n+1層的
for( int i = 0;i < g_nCurDirLayer - ( FileInfo.nLayer + 1 ); i ++ ) {
_chdir ( ".."); //返回上層文件夾(即父文件夾)
}
g_nCurDirLayer = FileInfo.nLayer + 1;
}
ofstream ofDest;
ofDest.open( FileInfo.szFileName ,ios::out | ios::binary ); //以二進制寫方式打開文件
char * pBuf = new char[BUF_LEN];
int nTimes = FileInfo.nLength / BUF_LEN;
int nRemain = FileInfo.nLength % BUF_LEN;
int i;
for( i = 0;i < nTimes; i ++) {
ifZip.read( pBuf,BUF_LEN);
ofDest.write( pBuf,BUF_LEN);
}
ifZip.read( pBuf,nRemain);
ofDest.write( pBuf,nRemain);
delete [] pBuf;
ofDest.close();
}
}
ifZip.close();
}
int main( int argc ,char * argv[])
{
if( argc == 1 )
return 0;
if( stricmp( argv[1],"-e") == 0 ) {
g_ofData.open(argv[3],ios::out | ios::binary); //以二進制寫方式打開文件
CompressDir( argv[2]);
g_ofData.close();
}
else if( stricmp( argv[1],"-x") ==0 )
DeCompressDir( argv[2]);
return 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -