尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

简化版文件封包解包程序

简化版文件封包解包程序
📅 发布时间:2026/6/20 16:03:10

简化版文件封包解包程序

三个部分

文件头

索引表

文件数据

索引表的每个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;
}

 

相关新闻

  • 2025年商用厨房设备厂家推荐:耀兴厨具领衔不锈钢排烟系统技术革新,解析行业十大实力品牌竞争优势 - 品牌企业推荐师(官方)
  • 2026年GEO优化源码搭建口碑排行榜哪家好 - 源码云科技
  • 基于TensorRT的大模型推理压测报告模板分享

最新新闻

  • 实战分布式锁
  • 2026无锡钻石回收榜首TOP|行业翘楚,高溢价透明变现标杆 - 讯息早知道
  • 2026年上海梅雨季旧房翻新全攻略:防潮防霉与靠谱机构推荐 - 优家闲谈
  • 构建实时语音转写系统:TMSpeech技术架构与应用实践
  • 2026在无锡回收首饰不玩虚高引流,线上预估价≈线下成交价,所有收费提前说明 - 讯息早知道
  • 如何快速掌握Nintendo Switch游戏备份:NxDumpTool终极指南

日新闻

  • 信任的进化:技术实现详解——如何用JavaScript构建博弈论模拟器
  • Terrakube自定义工作流:如何集成OPA、Infracost等工具扩展IaC能力
  • grunt-concurrent快速入门:5分钟学会并行运行Grunt任务

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号