当前位置:操作系统 > Unix/Linux >>

在Windows下C++实现UNIX中的GZ格式的解压缩

天在做项目中遇到一个问题,项目中需要开发一个PC工具(要求是Windows),其中需要将一些文件打包成gz文件,gz文件是UNIX系统中的压缩文件,后来找了找网上的资源,只有解压的C++源码,没有告诉你如何进行GZ格式的压缩,当然了,你还可以使用7Z软件对文件进行GZ解压缩。而本篇文章将用另外一个思路去实现GZ格式的解压缩。

 

首先,创建一个C++的工程项目,这里使用MFC窗体项目。

 

功能很简单,先看下整个窗体设计:

image

 

上面一排通过“选择文件”在下面的列表中显示文件路径,然后通过“压缩”按钮,保存到指定的目录中。

 

 image

下面一排通过”选择文件”选择gz格式的压缩包,然后通过“解压”按钮,保存到指定的目录中。、

 

 image

界面的功能就是这样,下面我来介绍下一些主要核心的功能。

 

首先,来看GZ的一个处理类:

GZHelper.h 头文件

//GZ解压缩类(配合tar.exe的可执行文件)
class GZHelper
{
public:
 GZHelper();
 virtual ~GZHelper();
 static void Compress(char* gzFilePath, int fileNum, char* file, ...); //压缩,(压缩包路径,文件个数,可变参数的文件列表)
 static void Compress(char* gzFilePath, int fileNum, char** files); //压缩,(压缩包路径,文件个数,文件列表)
 static void Decompress(char* folderPath, char* gzFilePath); //解压,(解压目录, 压缩包路径)

private:
 static CString ConvertToUnix(CString winFile); //将Window上的路径格式转换为UNIX路径格式
 static void FindFile(CString path, CString outPath); //遍历目录,并将目录中的所有文件移动到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 + "" ";
 }
 
 //执行命令
 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);
}

// 将Windows下的路径转换为UNIX路径
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
  {
   //移动文件
   MoveFile(fileFind.GetFilePath(), outPath + "\" + fileFind.GetFileName());
  }
 }

 fileFind.Close();
}通过代码中,我们看到两个方法Compress和Decompress,这里就是作为最核心的函数。

实际上,原理就是通过windows上的命令提示符cmd去调用一个tar的在Windows下编译好的一个命令包,这个包的目录内容如下:

image

实际上它是利用cygwin1.dll组件,将UNIX上的tar命令转换到Windows平台上运行。

这个包我会在连同工具和源码稍后在文章末尾一起奉上。

我们看到,在Compress中我们使用到"cd”命令符,这里是需要将cmd当前的路径设置到应用程序里面的一个tar包的路径上。

“&&”符号可以在单条指令中复合执行。

注意这里的command,在字符串路径中最好需要用"""将字符串隔开,这是为了防止字符串中的路径包括空格字符。

system函数执行cmd命令。

另外,我们看到ConverToUnix函数,它是用来表示将Windows下的路径转换为cygwin下的虚拟UNIX路径:

这是什么意思呢?现在我打开一个cygwin.exe工具,执行df命令:

image

补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,