21xrx.com
2025-03-29 20:06:15 Saturday
文章检索 我的文章 写文章
C++实现文件夹压缩
2023-07-11 12:28:03 深夜i     120     0
C++ 文件夹压缩 实现

随着互联网和移动设备的普及,数据传输和存储需求也越来越大。为了方便传输和节约存储空间,文件压缩成为了一种常见的解决方案。在许多情况下,我们不仅需要压缩单个文件,也需要将整个文件夹压缩成一个压缩包。本文将介绍如何使用C++实现文件夹压缩。

一、准备工作

在开始实现之前,我们需要安装一个开源的压缩库,例如zlib或libzip。这些库提供了各种压缩和解压缩算法,包括gzip,zip和tar等。我们需要在代码中引用这些库文件,并在编译时链接这些库。

二、压缩文件夹

压缩一个文件夹需要将文件夹中的所有文件和子文件夹压缩成一个文件,然后再将这个文件压缩成一个zip或tar文件。以下是一个简单的实现示例:

#include <zip.h>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define BUF_SIZE 4096
void add_folder(zip_t* archive, const char* path, const char* folder_name) {
  char folder_path[1024];
  sprintf(folder_path, "%s/%s", path, folder_name);
  zip_source_t* source = zip_source_win32ify(zip_source_folder(folder_path, 0), 0);
  zip_int64_t index = zip_add(archive, folder_name, source);
  zip_close_source(source);
  if (index < 0) {
    std::cout << "Failed to add folder to archive" << std::endl;
    exit(EXIT_FAILURE);
  }
  std::cout << "Added " << folder_name << std::endl;
}
void add_file(zip_t* archive, const char* path, const char* file_name) {
  char file_path[1024];
  sprintf(file_path, "%s/%s", path, file_name);
  zip_source_t* source = zip_source_file(zip_open(file_path, 0, 0), 0, 0, 0);
  zip_int64_t index = zip_add(archive, file_name, source);
  zip_close_source(source);
  if (index < 0) {
    std::cout << "Failed to add file to archive" << std::endl;
    exit(EXIT_FAILURE);
  }
  std::cout << "Added " << file_name << std::endl;
}
void compress_folder(const char* path, const char* output_filename) {
  zip_t* archive = zip_open(output_filename, ZIP_CREATE | ZIP_EXCL, 0);
  if (!archive) {
    std::cout << "Failed to open archive" << std::endl;
    exit(EXIT_FAILURE);
  }
  add_folder(archive, path, "");
  int num_entries = zip_get_num_entries(archive, 0);
  std::cout << "Compressed " << num_entries << " entries" << std::endl;
  zip_close(archive);
}
int main(int argc, char** argv) {
  if (argc != 3)
    std::cout << "Usage: program.exe folder_path output_filename" << std::endl;
    return 0;
  
  compress_folder(argv[1], argv[2]);
  return 0;
}

上面的代码实现了将文件夹压缩为一个zip文件。add_folder函数将文件夹添加到压缩包中,add_file函数将文件添加到压缩包中。compress_folder函数将指定的文件夹压缩到指定的压缩包中。该程序的输入参数为文件夹路径和输出zip文件名。输出示例:

Added []
Added [hello.txt]
Added [world.txt]
Added [subfolder1]
Added [subfolder1/hello2.txt]
Compressed 5 entries

三、解压文件夹

解压缩文件夹与压缩相反,需要先解压缩zip或tar文件,然后再递归地解压缩每个文件和子文件夹。以下是一个简单的实现示例:

#include <zip.h>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define BUF_SIZE 4096
void extract_entry(zip_t* archive, zip_uint64_t index, const char* dest_path) {
  zip_file_t* file = zip_fopen_index(archive, index, 0);
  if (!file) {
    std::cout << "Failed to open file in archive" << std::endl;
    exit(EXIT_FAILURE);
  }
  char buf[BUF_SIZE];
  zip_int64_t len = 0;
  FILE* out = fopen(dest_path, "wb");
  if (!out) {
    std::cout << "Failed to open output file" << std::endl;
    exit(EXIT_FAILURE);
  }
  while ((len = zip_fread(file, buf, BUF_SIZE)) > 0) {
    fwrite(buf, 1, len, out);
  }
  fclose(out);
  zip_fclose(file);
}
void extract_folder(zip_t* archive, zip_uint64_t index, const char* path) {
  const char* name = zip_get_name(archive, index, 0);
  char dest_path[1024];
  sprintf(dest_path, "%s/%s", path, name);
  char dest_folder_path[1024];
  sprintf(dest_folder_path, "%s/%s", path, name);
  if (strrchr(dest_folder_path, '/') != NULL) {
    *(strrchr(dest_folder_path, '/')) = '\0';
    mkdir(dest_folder_path, 0777);
  }
  if (zip_entry_isdir(archive, index, 0)) {
    int num_entries = zip_get_num_entries(archive, 0);
    for (int i = 0; i < num_entries; i++) {
      if (zip_entry_isdir(archive, i, 0)) {
        continue;
      }
      if (strncmp(name, zip_get_name(archive, i, 0), strlen(name)) == 0) {
        extract_entry(archive, i, dest_folder_path);
      }
    }
  } else {
    extract_entry(archive, index, path);
  }
}
void extract_archive(const char* filename, const char* path) {
  zip_t* archive = zip_open(filename, 0, 0);
  if (!archive) {
    std::cout << "Failed to open archive" << std::endl;
    exit(EXIT_FAILURE);
  }
  int num_entries = zip_get_num_entries(archive, 0);
  for (int i = 0; i < num_entries; i++) {
    extract_folder(archive, i, path);
  }
  zip_close(archive);
}
int main(int argc, char** agrv) {
  if (argc != 3) {
    std::cout << "Usage: program.exe archive_filename extract_directory" << std::endl;
    return 0;
  }
  extract_archive(argv[1], argv[2]);
  return 0;
}

上面的代码实现了将zip文件解压到指定的文件夹中。extract_entry函数将压缩包中的单个文件解压到指定路径,extract_folder函数递归地解压缩文件夹。extract_archive函数将指定的压缩包解压到指定的文件夹中。程序的输入参数为zip文件名和输出文件夹路径。输出示例:

Creating directory [./archive/tar]
Creating directory [./archive/tar/subfolder1]
Creating directory [./archive/tar/subfolder2]
Extracted [hello.txt]
Extracted [world.txt]
Extracted [subfolder1/hello2.txt]

总结

本文介绍了如何使用C++实现文件夹压缩。我们使用了zlib和libzip这两个常用的开源压缩库。在压缩文件夹时,我们将每个文件和子文件夹添加到压缩包中,并使用zip或tar格式进行打包。而在解压缩文件夹时,我们需要递归地解包每个文件和子文件夹。这些函数都可以在zlib和libzip的API文档中找到。这里介绍的只是一些常见的用法。

  
  

评论区