枣庄市网站建设_网站建设公司_HTML_seo优化
2025/12/27 21:33:00 网站建设 项目流程

简化版文件封包解包程序

三个部分

文件头

索引表

文件数据

索引表的每个offset记录的是每个诗句相对于数据区起始位置的偏移量

// 简化版文件封包解包程序
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>#define PACK_FILE "archive.dat"
#define MAX_PATH 256// 文件头结构
struct FileHeader
{int file_count;  // 文件数量long data_start; // 数据区起始位置
};// 文件索引结构
struct FileIndex
{char name[256]; // 文件名long offset;    // 每个文件相对于数据区起始位置的偏移long size;      // 文件大小
};// 获取文件大小
long get_file_size(FILE *fp)
{long size;fseek(fp, 0, SEEK_END);size = ftell(fp);fseek(fp, 0, SEEK_SET);return size;
}// 打包函数
void pack_folder(const char *folder)
{printf("正在打包文件夹: %s\n", folder);// 打开文件夹DIR *dir = opendir(folder);if (!dir){printf("无法打开文件夹\n");return;}// 收集文件信息struct dirent *entry;struct FileIndex *indexes = NULL;int file_count = 0;long current_offset = 0;// 第一遍:统计文件while ((entry = readdir(dir)) != NULL){if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)continue;char fullpath[512];snprintf(fullpath, sizeof(fullpath), "%s/%s", folder, entry->d_name);struct stat st;if (stat(fullpath, &st) == 0 && S_ISREG(st.st_mode)){file_count++;}}if (file_count == 0){printf("文件夹为空\n");closedir(dir);return;}// 分配索引数组indexes = malloc(file_count * sizeof(struct FileIndex));if (!indexes){printf("内存分配失败\n");closedir(dir);return;}// 第二遍:收集文件信息
    rewinddir(dir);int idx = 0;while ((entry = readdir(dir)) != NULL){if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)continue;char fullpath[512];snprintf(fullpath, sizeof(fullpath), "%s/%s", folder, entry->d_name);struct stat st;if (stat(fullpath, &st) == 0 && S_ISREG(st.st_mode)){// 获取文件大小FILE *fp = fopen(fullpath, "rb");if (fp){strncpy(indexes[idx].name, entry->d_name, 255);indexes[idx].name[255] = '\0';indexes[idx].offset = current_offset;indexes[idx].size = get_file_size(fp);current_offset += indexes[idx].size;fclose(fp);idx++;}}}closedir(dir);// 创建封包文件FILE *pack = fopen(PACK_FILE, "wb");if (!pack){printf("无法创建封包文件\n");free(indexes);return;}// 写入文件头struct FileHeader header;header.file_count = file_count;header.data_start = sizeof(struct FileHeader) + file_count * sizeof(struct FileIndex);fwrite(&header, sizeof(struct FileHeader), 1, pack);// 写入索引表fwrite(indexes, sizeof(struct FileIndex), file_count, pack);// 写入文件数据for (int i = 0; i < file_count; i++){char fullpath[512];snprintf(fullpath, sizeof(fullpath), "%s/%s", folder, indexes[i].name);FILE *src = fopen(fullpath, "rb");if (src){char buffer[4096];size_t read;while ((read = fread(buffer, 1, sizeof(buffer), src)) > 0){fwrite(buffer, 1, read, pack);}fclose(src);printf("打包: %s (%ld 字节)\n", indexes[i].name, indexes[i].size);}}fclose(pack);free(indexes);printf("打包完成! 共 %d 个文件\n", file_count);
}// 解包函数
void unpack_files(const char *packfile)
{printf("正在解包: %s\n", packfile);FILE *pack = fopen(packfile, "rb");if (!pack){printf("无法打开封包文件\n");return;}// 读取文件头struct FileHeader header;if (fread(&header, sizeof(struct FileHeader), 1, pack) != 1){printf("读取文件头失败\n");fclose(pack);return;}printf("文件数量: %d\n", header.file_count);// 读取索引表struct FileIndex *indexes = malloc(header.file_count * sizeof(struct FileIndex));if (!indexes){printf("内存分配失败\n");fclose(pack);return;}if (fread(indexes, sizeof(struct FileIndex), header.file_count, pack) != header.file_count){printf("读取索引表失败\n");free(indexes);fclose(pack);return;}// 定位到数据区
    fseek(pack, header.data_start, SEEK_SET);// 解包所有文件for (int i = 0; i < header.file_count; i++){printf("解包: %s (%ld 字节)\n", indexes[i].name, indexes[i].size);FILE *out = fopen(indexes[i].name, "wb");if (!out){printf("无法创建文件: %s\n", indexes[i].name);continue;}// 读取并写入文件数据long remaining = indexes[i].size;char buffer[4096];// 这段代码是用于分块读取文件数据的逻辑。/*remaining 变量
表示文件还剩下多少字节需要读取
初始值是文件总大小
每次读取后减少已读取的字节数*/
/*
这个循环就像用勺子舀水:
remaining = 锅里还剩多少水
buffer = 勺子的大小(固定4KB)
to_read = 这次要舀多少(如果水少就少舀点)
每次舀一勺,直到舀完为止*/while (remaining > 0){size_t to_read = sizeof(buffer);if (remaining < (long)to_read){to_read = remaining;}size_t read = fread(buffer, 1, to_read, pack);if (read == 0)break;fwrite(buffer, 1, read, out);remaining -= read;}fclose(out);}free(indexes);fclose(pack);printf("解包完成!\n");
}// 主函数
int main(int argc, char *argv[])
{if (argc != 3){printf("使用方法:\n");printf("  打包: %s -pack 文件夹名\n", argv[0]);printf("  解包: %s -unpack archive.dat\n", argv[0]);return 1;}if (strcmp(argv[1], "-pack") == 0){pack_folder(argv[2]);}else if (strcmp(argv[1], "-unpack") == 0){unpack_files(argv[2]);}else{printf("参数错误\n");return 1;}return 0;
}

 

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询