对于一个项目来说,必须阅读一些 zip 文件。 一切都很好,但是什么时候想要从 zip 文件中的文件夹中读取内容 这是行不通的。或者我只是不知道 zip 在 C++ 中是如何工作的。 我在互联网上搜索了所有内容,但找不到答案。
据我回忆,过去使用 minizip 时,文件夹层次结构中的所有文件都会同时返回。您只需比较每个文件的路径名即可找出哪些与您要读取的文件夹匹配。
zipFile zip = unzOpen(zipfilename);
if (zip) {
if (unzGoToFirstFile(zip) == UNZ_OK) {
do {
if (unzOpenCurrentFile(zip) == UNZ_OK) {
unz_file_info fileInfo;
memset(&fileInfo, 0, sizeof(unz_file_info));
if (unzGetCurrentFileInfo(zip, &fileInfo, NULL, 0, NULL, 0, NULL, 0) == UNZ_OK) {
char *filename = (char *)malloc(fileInfo.size_filename + 1);
unzGetCurrentFileInfo(zip, &fileInfo, filename, fileInfo.size_filename + 1, NULL, 0, NULL, 0);
filename[fileInfo.size_filename] = '\0';
// At this point filename contains the full path of the file.
// If you only want files from a particular folder then you should compare
// against this filename and discards the files you don't want.
if (matchFolder(filename)) {
unsigned char buffer[4096];
int readBytes = unzReadCurrentFile(zip, buffer, 4096);
// Do the rest of your file reading and saving here.
}
free(filename);
}
unzCloseCurrentFile(zip);
}
} while (unzGoToNextFile(zip) == UNZ_OK);
}
unzClose(zip);
}
我目前没有能力测试这段代码,所以可能会有一些错误,但希望你能看到它应该如何工作的总体思路。
基于詹姆斯的回答,这里是经过测试的代码。
bool mftpd_unzip(char *file, char *dest)
{
char ch1, ch2;
int tpos;
char *tmp;
int dlen;
int offset;
char *dir = (char *)malloc(TRANSPORT_MAX_BUFFER_SIZE);
zipFile zip = unzOpen(file);
bool ret = false;
void *lh = mftpd_log_instance();
unsigned char buffer[4096];
FILE *fd = NULL;
if(zip)
{
if(unzGoToFirstFile(zip) == UNZ_OK)
{
/* Create the dest dir */
dlen = sprintf(dir, "%s", dest);
dir[dlen] = 0x0;
create_nested_directories(dir, dlen);
do
{
if(unzOpenCurrentFile(zip) == UNZ_OK)
{
unz_file_info fileInfo;
memset(&fileInfo, 0, sizeof(unz_file_info));
if(unzGetCurrentFileInfo(zip, &fileInfo, NULL, 0, NULL, 0, NULL, 0) == UNZ_OK)
{
char *filename = (char *)malloc(fileInfo.size_filename + 1);
unzGetCurrentFileInfo(zip, &fileInfo, filename, fileInfo.size_filename + 1, NULL, 0, NULL, 0);
filename[fileInfo.size_filename] = '\0';
if(filename[fileInfo.size_filename-1] == '/')
{
}
else
{
tmp = strrchr(filename, '/');
if(tmp)
{
tpos = (int)(tmp - filename) + 1;
ch1 = filename[tpos];
/* Create the dest dir */
offset = sprintf(dir+dlen, "%s", filename);
*(dir+dlen+offset) = 0x0;
ch2 = dir[(dlen + tpos)];
dir[(dlen + tpos)] = 0x0;
//log_data(LOG_VERBOSE, lh, "Complete dir: %s", dir);
create_nested_directories(dir, (dlen+tpos));
dir[(dlen + tpos)] = ch2;
//log_data(LOG_VERBOSE, lh, "Complete file: %s", dir);
fd = fopen(dir, "w+");
if(fd == NULL)
{
//log_data(LOG_VERBOSE, lh, "Could not open file %s", dir);
goto end;
}
dir[dlen] = 0x0;
filename[tpos] = ch1;
while(true)
{
offset = unzReadCurrentFile(zip, buffer, sizeof(buffer));
if(offset > 0)
{
buffer[offset] = 0;
fwrite(buffer, 1, offset, fd);
//log_data(LOG_VERBOSE, lh, "Wrote %d bytes of data\n%s", offset, buffer);
}
else if(offset == 0) //end of file
{
fclose(fd);
fd = NULL;
//log_data(LOG_VERBOSE, lh, "Reached end of file");
break;
}
else //if offset < 0
{
fclose(fd);
fd = NULL;
//log_data(LOG_ERROR, lh, "Got zlib error %d", offset);
break;
}
}
}
else
{
//log_data(LOG_ERROR, lh, "File: %s, check here ...", filename);
}
}
}
}
}while(unzGoToNextFile(zip) == UNZ_OK);
}
unzClose(zip);
ret = true;
}
end:
free(dir);
return ret;
}