windows下解压tar.gz文件
2021-05-13 01:27
标签:标识 .dll 命令行 www. manual 文章 war com 数据 最近做的一个项目,使用小工具代替人工提交到网站并获取结果。 在开发过程中碰到了一个问题。 网站返回的格式为tar.gz文件。第一个想到的方式是直接用第三方工具,使用的是7z。但用户那里使用的系统为win10,不以管理员身份运行会没有调用第三方工具的权限。遂决定用库解决该问题。 这里记录下windows下解压tar.gz的一些问题。 其实tar.gz是两次封装。 第一次是tar打包(这里不会压缩,文件反而会更大),第二次是gz文件的算法压缩。 解压GZ文件使用的是zlib库。 这里说一下zlib的使用过程。 一开始我是图懒直接从官网下载的windows develop版本,包含头文件,静态库和dll。但运行过程中出现了缺少zlib1.dll的问题。经过反复的折腾,没有解决。他这个库生成时间是2005年,可能在新版windows下运行会有问题把。 本人对系统了解还是不多,没有找到深层次的原因。如果有大神知道原理请告知。 在此之后下载了新版并进行编译。具体编译过程忘记了,挺顺利的。在vs命令行里执行一条命令后,会直接生成vs工程项目。选择静态库或动态库编译即可。 不知道这里能不能发csdn的连接,我是根据这篇文章来编译的:http://blog.csdn.net/shellching/article/details/8116622。 当然我用的版本是vs2015。用这种方法也能顺利通过。 接下来就是解压了。一开始我从网上找到的资料全是compress和uncompress,后来发现: 错啦! 压根就不是这么解压的。 具体原因没有详细了解到,大体上我的理解就是,其实gz文件需要一个头来标识压缩级别等信息。而compress和uncompress只是压缩字节流,单纯地调用uncompress而不知道数据的开始位置和数据的压缩信息的话,是无法正常压缩的。 下面是解压代码: //初始化结构体 z_stream strm = { 0 }; strm.zalloc = Z_NULL; strm.zfree = Z_NULL; //下面分别初始化源数据,源数据长度,目标数据长度和目标数据地址 strm.next_in = srcBuffer; //下面函数的第二个参数在头文件的函数说明里有,这里的这个参数意思是自动判断信息头 //执行解压缩 res = inflate(&strm, Z_NO_FLUSH); //回收资源 上面的代码我去掉了结果判断的部分,具体的结果判断大家参考头文件的信息把。我其实在代码里没有进行详细判断,只是简单判断了成功失败,并没有返回原因。这里就不贴上来坑大家了。 有几点注意事项: 1,目标内存长度需要足够。当然不够也没关系,该函数会在执行时发现并返回这个错误,在判断后逐步增加缓冲区即可。 2,转换成功后目标数据的长度为:dstLen - strm.avail_out。 3,如果你编译后使用这些函数,这个程序会莫名其妙地崩掉。 4,如果你是新手(现在没啥新手在VS上用这个了把。。。),可能会报无法连接的错误,当然你引入了lib还是会报。 先说下为何会报连接错误,需要加一个宏ZLIB_WINAPI,如果有新手在看的话,跟大家分享下。 一个库,无论是静态还是动态。在有头文件的时候,有两个地方需要注意,一是你编译库的时候,导出函数前面有没有加export,第二个是你引入库的时候,导出函数前面是不是import。 有些库因为要处理跨平台的问题,库的源码的宏定义会非常复杂,这时候要仔细观察,设置响应的宏确定库函数的正确引入和导出,如果你用VS的话,VS会根据宏定义的状态来高亮具体代码用到哪个宏。 在编译和引入的时候都要注意。 接下来,在崩溃之后,各种google原因,但始终没有发现是为什么,因为当时没有解压成功,我也一度怀疑自己的代码有问题,或者库有问题。 在这里,感谢一位大神:http://blog.csdn.net/u013283835/article/details/70311499 真是跪谢。这是怎么发现的。祝您能修到孙艺珍。 根据这位大神的说法,把预处理器中的ASMINF这个宏去掉。执行程序将转换出来的字节流写入文件。搞定了。 这里鄙视下CSDN:本人的csdn因为前几年给别人发QSS代码被封了。我也是醉了,发个QSS代码都能封。就这还搞技术论坛。呵呵。 接下来就进行tar文件的解析了。最开始想到的使用libarchive库。 嗯。编译,连接,导入,使用。在经历过种种挫折后,我突然发现:libarchive不支持全路径,只能打开当前工作目录下的文件,当然也可能是我某个配置没有配好,但libarchive的资料实在是太少了。 官方文档也只有很粗略的解释。而且在win10下,如果程序安装在C盘program files下,运行程序是没有创建文件权限的,在其他盘则需要不停设置当前路径。放弃。这个库真不是一般的难用。 查了下tar文件的格式: http://blog.chinaunix.net/uid-20357359-id-1963469.html https://www.gnu.org/software/tar/manual/html_node/Standard.html 嗯,貌似做简单的拆包不复杂吗。外加我做的小项目中tar文件本就是自动生成的,只有一级目录。自己解决把。 下面是代码: typedef struct posix_header { //填充字节块
注意: 1,我还是去掉了返回判断的代码,如果想完成健壮代码请判断各种状态返回值。 2,这段代码不能解压包含文件夹或者多级目录的tar文件,也不能解压特殊文件,也没有判断字节偏移等数据。 简单来说,这段代码只能保证我这个小项目的需求。而且很大程度上满足不了其他需求。 经过上面两步,基本上满足了我的需求。在这里分享给大家。 windows下解压tar.gz文件 标签:标识 .dll 命令行 www. manual 文章 war com 数据 原文地址:http://www.cnblogs.com/xiaoBay/p/7567249.html
strm.opaque = Z_NULL;
strm.avail_in = srcLength;
strm.avail_out = dstLength;
strm.next_out = dstBuffer;
int res = inflateInit2(&strm, MAX_WBITS + 32);
inflateEnd(&strm);
char name[100];
char mode[8];
char uid[8];
char gid[8];
char size[12];
char mtime[12];
char chksum[8];
char typeflag;
char linkname[100];
char magic[6];
char version[2];
char uname[32];
char gname[32];
char devmajor[8];
char devminor[8];
char prefix[155];
}TAR_HEADER;//参数为目标路径、tar缓冲区,缓冲区长度
void ExtractTar(const char *dstDir, BYTE *buffer, uLongf len)
{
uLongf index = 0;
while (true)
{
if (index == len - 1)
{
return;
}
TAR_HEADER newHeader = { 0 };
memcpy(&newHeader, buffer + index, sizeof(TAR_HEADER));
index += sizeof(TAR_HEADER);
if (strcmp(newHeader.name, "") == 0)
{
return;
}
char fileFullPath[MAX_PATH] = { 0 };
memcpy(fileFullPath, dstDir, strlen(dstDir));
memcpy(fileFullPath + strlen(dstDir), newHeader.name, strlen(newHeader.name));
FILE *newFile = NULL;
fopen_s(&newFile, fileFullPath, "wb+");long size = strtol(newHeader.size, (char **)(&(newHeader.size) + 12), 8);
size_t res = fwrite(buffer + index, 1, size, newFile);
fclose(newFile);
index += size;
上一篇:Win10 UWP开发系列:实现Master/Detail布局
下一篇:背水一战 Windows 10 (24) - MVVM: 通过 Binding 或 x:Bind 结合 Command 实现,通过非 ButtonBase 触发命令
文章标题:windows下解压tar.gz文件
文章链接:http://soscw.com/index.php/essay/84936.html