Today, I encountered a problem in my project. In this project, I need to develop a PC tool (Windows Required). In this case, I need to package some files into a gz file, the gz file is a compressed file in the UNIX system. Later, I found the online resources and only decompressed the C ++ source code. I didn't tell you how to compress the file in the GZ format. Of course, you can also use7Z SoftwareDecompress the file in GZ. In this article, we will use another idea to decompress the GZ format.
First, create a C ++ project. Here we use the MFC form project.
The function is very simple. Let's take a look at the design of the entire form:
In the above row, select "select file" to display the file path in the following list, and then click "compress" to save it to the specified directory.
Select a file in the gz format in the following row, and click "decompress" to save the package to the specified directory. ,
This is the interface function. Next I will introduce some of the main core functions.
First, let's look at a processing class of GZ:
GZHelper. h header file
// Gzdecompressed class (Executable File of mongotar.exe) class GZHelper {public: GZHelper (); virtual ~ GZHelper (); static void Compress (char * gzFilePath, int fileNum, char * file ,...); // compression, (compressed package path, file count, file list with variable parameters) static void Compress (char * gzFilePath, int fileNum, char ** files); // compression, (compressed package path, number of files, file list) static void Decompress (char * folderPath, char * gzFilePath); // Decompress (Decompress directory, compressed package path) private: static CString ConvertToUnix (CString winFile); // convert the path format on the Window to the UNIX path format static void FindFile (CString path, CString outPath); // traverse the directory, and move all the files in the directory to outPath };
GZHelper. cpp
Void GZHelper: Compress (char * gzFilePath, int fileNum, char * file ,...) {va_list argptr; va_start (argptr, gzFilePath); va_arg (argptr, int); char ** files; files = new char * [fileNum]; for (int index = 0; index <fileNum; index ++) {char * file = va_arg (argptr, char *); CString str_file; str_file = file; files [index] = new char [str_file.GetLength ()]; memcpy (files [index], file, str_file.GetLength (); files [index] [str_file.GetLength ()] = 0 ;} va_end (argptr); Compress (gzFilePath, fileNum, files);} void GZHelper: Compress (char * gzFilePath, int fileNum, char ** files) {CString str_gzFilePath (gzFilePath ); CString folderPath = str_gzFilePath.Left (str_gzFilePath.ReverseFind ('\') + 1); CString command = "cd"; command = command + Path: StartupPath () + "tar &" + Path: GetDrive () + "& tar.exe zcPf"; CString unix_str_gzfile = ConvertToUnix (str_gzFilePath ); command = command + "\" "+ unix_str_gzfile +" \ ""; for (int index = 0; index <fileNum; index ++) {char * file = files [index]; CString str_file; str_file = file; CString unix_str_file = ConvertToUnix (str_file ); command = command + "\" "+ unix_str_file +" \ "";} // run the command system (command);} void GZHelper: Decompress (char * folderPath, char * gzFilePath) {CString str_folderPath (folderPath); CString str_gzFilePath (gzFilePath); CString command = "cd"; command = command + Path: StartupPath () + "tar &" + Path: GetDrive () + "& tar.exe zxvf"; CString unix_str_gzfile = ConvertToUnix (str_gzFilePath ); command = command + "\" "+ unix_str_gzfile +" \ ""; system (command); CString outPath = str_folderPath + "\ demo"; CreateDirectory (outPath, NULL ); CString inPath = Path: StartupPath () + "tar \ cygdrive"; GZHelper: FindFile (inPath, outPath); RemoveDirectory (inPath );} // convert the path in Windows to the UNIX path CString GZHelper: ConvertToUnix (CString winFile) {CString unixFile; unixFile = winFile; unixFile. replace ("\", "/"); unixFile = "/cygdrive/" + unixFile. mid (0, 1) + unixFile. mid (2, unixFile. getLength ()-2); return unixFile;} void GZHelper: FindFile (CString path, CString outPath) {CString szDir = path + "\\*. * "; CFileFind fileFind; BOOL result = fileFind. findFile (szDir); while (result) {result = fileFind. findNextFile (); if (fileFind. isDots () continue; if (fileFind. isDirectory () {GZHelper: FindFile (fileFind. getFilePath (), outPath);} else {// move the file MoveFile (fileFind. getFilePath (), outPath + "\" + fileFind. getFileName () ;}} fileFind. close ();}
In the code, we can see two methods: Compress and Decompress. Here is the core function.
In fact, the principle is to call a tar command package compiled in windows through the command prompt cmd on Windows. The contents of this package are as follows:
In fact, it uses the cygwin1.dll component to convert the tar command on UNIX to run on Windows.
This package will be provided at the end of the article together with the tool and source code.
We can see that in Compress, we use"Cd" commandIn this example, you need to set the current cmd path to the path of a tar package in the application.
"&" SymbolYou can execute multiple commands in a single command.
Note the command here,It is best to use "\" to separate strings in the string path, to prevent the path in the string from including space characters.
System FunctionsRun the cmd command.
In addition, we can see that the ConverToUnix function is used to convert the path in Windows to the virtual UNIX path in cygwin:
What does this mean? Now I open a cygwin.exe tool and execute the df command:
As you can see,The path on each disk corresponds to the specific virtual path in cygwin., Such as D: corresponding to/cygdrive/d
The ConverToUnix method is to convert the path on the disk to a recognizable virtual path under cygwin.
In tar.exe for simple compression and decompression instructions, specific can refer to: http://www.21andy.com/blog/20060820/389.html
You may notice: static void Compress (char * gzFilePath, int fileNum, char * file ,...);
This method is very interesting. It indicatesVariable parameters. "..." To Compress any number of files. In the methodVa_list, va_start, va_arg, va_endAs a parameter pointer, va_list can move the pointer to the next parameter through va_arg to traverse the value of a variable parameter.
In addition, I added a directory selection class to the tool:
Header file:
// Directory selection class CFolderDialog {public: CFolderDialog (LPCTSTR title, DWORD dwFlags = BIF_STATUSTEXT | BIF_USENEWUI | BIF_RETURNONLYFSDIRS); virtual ~ CFolderDialog (); virtual INT_PTR DoModal (HWND hwnd); CString GetPathName () const; private: BROWSEINFO browseInfo; CString m_path ;};
Cpp file:
/* CFolderDialog Begin */CFolderDialog::CFolderDialog(LPCTSTR title, DWORD dwFlags){char szDir[MAX_PATH]; ITEMIDLIST *pidl; // browseInfo.lpszTitle = title; browseInfo.ulFlags = dwFlags; }CFolderDialog::~CFolderDialog(){}INT_PTR CFolderDialog::DoModal(HWND hwnd){char szDir[MAX_PATH];ITEMIDLIST *pidl;browseInfo.pidlRoot = NULL; browseInfo.pszDisplayName = szDir;browseInfo.hwndOwner = hwnd;browseInfo.lpfn = NULL; browseInfo.lParam = 0; browseInfo.iImage = 0; pidl = SHBrowseForFolder(&browseInfo); if(pidl == NULL) return 2; if(!SHGetPathFromIDList(pidl, szDir))return 2;m_path = szDir;return 1;}CString CFolderDialog::GetPathName() const{return m_path;}/* CFolderDialog End */
How to call:
CFolderDialog folderDialog ("compressed to directory:"); int result = folderDialog. DoModal (this-> m_hWnd); if (result = 1 ){...}
Finally, the source code of the tool (containing the tar command package) is attached: GZCompressDemo.rar
Hope to help you!