SFC 开发日志:AES、.sy 格式与 Qt GUI
从 AES-128 原型出发,经历目录协议设计、Huffman 树序列化、压缩/解压主链路、CLI 稳定化,到 Qt GUI、策略模式重构和单文件发布,再到多线程流水线与编解码内核提速。
2025-09-29~30:项目初始化
创建基础文件结构和 Git 仓库,编写策划文档。最早一批提交是加密算法实验代码,项目起点是 AES 加密实验。
2025-10-01~05:AES-128 原型
实现完整 AES-128 加密,支持 ECB 模式。密码入口采用 SHA-256 派生,截取前 16 字节作为密钥。密钥扩展生成 44 个轮密钥字,10 轮加密包含 SubBytes、ShiftRows、MixColumns、AddRoundKey 四个标准变换。预计算 GF(2^8) 乘法表,用查表替代运行时计算。
2025-10-11~30:架构设计与并发框架
项目从单文件实验转向模块化。策划文档确定”压缩、加密、调度、数据交互”四层关系。
10-21:重构文件结构,目录按职责拆分为压缩模块、加密模块和数据流模块。10-2324:实现线程池的工作线程管理和任务分发,任务队列封装条件变量,提供线程安全的入队/出队;补上模块抽象接口、命名空间与数据块类型定义,压缩策略、加密策略、数据交互三类抽象接口落位。10-26:绘制压缩流程图,设计解压流程。10-2830:优化线程池任务调度,把任务队列列表和条件变量列表收口为任务队列管程;添加文件定位器,封装所有 seek 操作,负责在文件头、目录块和数据区之间定位。
2025-11-01~13:读取器原型与路径兼容性
文件头读取器从 Day6 原型迭代到 v0.1.5,逐步补齐位流读取、文件系统接入和读取流程修正。抛弃 POSIX,使用标准库 filesystem。引入队列辅助结构,为文件队列、目录队列和目录块解析打前站。首次尝试宽字符方案处理 Windows 路径。
2025-11-17~21:加载器与压缩主链路
引入文件头加载器和归档元数据入口,统一文件头字段、目录读取入口与归档元数据。读取器按职责演化为目录读取器。Huffman 频率统计模块完成,开始接入压缩模块,压缩主链路首次成型。
2025-11-23~30:Huffman 编码表与 AES-CFB
文件头写入模块迭代:文件头写入框架、编码表数据类、编码表生成/加载模块。编码树序列化固定为先序遍历——叶子 'l' + 字节值,内部节点 'r'。哈希容器替换为 unordered_map 提升查找性能。修复 sizeof 返回值类型问题和偏移量计算边界。
文件头加载模块迭代:文件头读取、AES-CFB 模式适配、IV 支持和目录块加载解析。AES 从 ECB 改为 CFB——CFB 不改变数据长度,便于在分割标准中记录 IV。
.sy 文件头固定 19 字节:两个魔数(0xDEADBEEF)夹住策略号、版本号和目录偏移量。
2025-12-01~06:数据块表示与压缩侧联通
压缩模块、加密模块、数据读取和数据写出模块统一使用字节向量作为数据块。模块只接收字节数据,不关心上游来源。整理命名空间,文件头加载分块读取采用迭代器混合状态机模式。
文件头写入扩展:目录协议增加符号链接标准,分块标准扩展为”块大小 + IV + 分块标识”。输出流程:写文件头 → 写目录块 → 读目录块 → 按块处理 → 目录块加密 → 回填大小。
2025-12-08~09:AES 模块补齐
AES 从独立算法代码转成归档流程模块。添加 GF(2^8) 乘法表(乘 2/3/9/11/13/14 六个查表),查表减少运行时乘法计算耗时。
2025-12-10~12:BFS 目录遍历与逻辑根目录
目录条目处理器采用 BFS 目录遍历。输入文件和目录先挂到逻辑根目录下,再由队列按层序遍历。目录块每写满 16KB 插入一条分块标准。BFS 直接服务目录恢复——解压器只按目录标准和子项数量推进队列,不需要外部目录描述文件。逻辑根目录解决多文件/多文件夹的森林合并问题。
2025-12-13~17:解压流程
解压主体是二进制目录读取器。内部维护文件队列、条目队列、目录队列就绪标志和块位置。读取器先验证魔数、读取文件头、定位目录偏移,逐块读取目录块,再交给条目解析器解析。
读取 .sy 文件 → 验证魔数 → 跳转到目录块偏移 → 按需解密目录块 → 解析文件队列和目录队列 → 创建目录结构 → 逐块读取数据区 → 解密 Huffman 树 → 重建树 → 解密压缩数据 → Huffman 解码 → 写回文件2025-12-18~25:工程整理与 CLI 交互
哈希容器替换为 unordered_map,CLI 相关代码整理。采用耦合设计:目录块、树数据、压缩数据、加密过程全部写进压缩/解压主循环。
2025-12-30~31:Huffman 单字符边界问题
数据块全部由同一字节组成时,Huffman 树只有一个叶子节点,常规构造失效。处理方式:叶子节点数为 1 时,编码直接写成 {0},长度记为 1。单字符文件和单字符数据块纳入标准流程。
2026-01-01~06:首个 CLI 预览版本
v1.0.0 Preview 发布。CLI 加密压缩与解压全流程完成。偏移量类型统一为 64 位无符号整数,目录缓冲区大小固定为 16KB,constexpr const 历史写法清理,README 补全。
2026-03-02~15:CLI 稳定化
条目类型改成强类型枚举(目录、文件、分块、逻辑根、符号链接五类标志),目录接口、工具类接口和文件已存在时的处理方式同步整理。目录块边界写入问题修复——目录条目恰好落在分块边界时产生空分块或解析错位。长路径尝试(\\?\ 前缀)因 API 限制放弃,保留 UTF-8 中文路径和常规 Windows 路径。移除 OpenSSL 依赖,改用 Windows CryptoAPI。
2026-04-01:构建系统迁移
从 GCC 迁移到 MSVC + CMake。关闭链接时优化(LTO),目的是使用 VS 性能分析报告。统一 C++20、Release 优化和 Windows 构建流程。
2026-04-12~15:GUI 工程建立
代码清理,开始编写 Qt Widgets。GUI 工程建立,CMake 配置和后台任务执行框架完成。GUI 设计隔离:CLI 核心工程和文件系统模块负责主逻辑,GUI 负责参数录入、结果展示和线程调度。修复目录偏移写入时机问题。
2026-04-16:Qt GUI 主体
GUI 主体围绕主窗口、后台工作对象和工作线程组织。主窗口收集源路径、输出目录、模式和密码,后台工作对象在工作线程调用主流程,进度通过信号送回 UI 线程。
主窗口 (UI线程) → 工作线程 → 后台工作对象 → 压缩/解压主循环 ← 进度 / 完成信号进度信号双层节流:主循环控制核心层回调频率,后台工作对象按时间和百分比变化量再做一层。窗口关闭时通过原子停止标志请求停止,析构阶段等待线程退出。
文件句柄和缓冲区释放:读取器完成标志、解压建文件、字节缓冲复用、Huffman 表容量释放都进入正式代码。
中文路径与编码处理
GUI 接入后暴露路径编码差异。Qt 层传入 UTF-8,filesystem 在 Windows 下可能关联本地代码页。修正规则集中在编码转换工具:Qt 边界处统一 UTF-8,进入核心层前转 UTF-8,进入文件系统前转路径对象,回到日志或 GUI 时转回 UTF-8。目录遍历和文件名序列化统一 u8string()。输出目录乱码修复:UTF-8 文本先转路径对象,再交给解压主循环。
Qt 工具链与系统兼容性
GUI 发布收敛到 Qt 6.2.4 LTS。MSYS2 MinGW 15.x 构建版本出现过 nanosleep64 缺失,Qt 6.10.1 部分在旧版 Windows 10 不稳定。Qt 6.2.4 统一图形界面、路径转换、线程模型和静态发布环境。兼容 Windows 10 1809+。
2026-04-17:多策略支持与发布形态调整
主流程原本把 Huffman 与 AES 写死。重构后引入压缩模式枚举、策略工厂、压缩与加密抽象接口和空实现,压缩和加密的组合改由运行时装配。压缩、解压主循环和目录读取器由依赖具体模块改为依赖接口。解压侧通过文件头策略号还原模式,策略号 0 映射 HuffmanAES。
四种模式:HuffmanAES 为默认模式,另有 HuffmanOnly、AESOnly、PackOnly。
发布形态调整:动态部署约 57MB,静态发布改用 Qt 6.2.4 静态库,构建开关控制,翻译文件和图片资源内嵌,背景图从 PNG 改 JPEG。默认发布体积约 16MB,不携带额外依赖。
2026-04-18~19:编码整理、翻译与工程清理
编码规则固定:GUI 输入统一转 UTF-8,核心层字符串按 UTF-8 组织,接触文件系统时转路径对象。编码转换职责全部归入编码转换工具。
GUI 多语言规则:界面文案统一 tr() 包装,翻译资源通过资源文件内嵌,语言选择优先 SFC_GUI_LANGUAGE,未指定时按系统语言。单 exe 发布下翻译不依赖外部目录。日志和技术状态文本保持英文。
工程整理:头文件、命名空间、.gitignore 和临时验证目录清理。代码布局与功能布局对齐。
2026-05-04~07:文档与 UML 整理
整理 Markdown 文档、项目说明与 UML/设计说明,对前期 GUI、策略模式和构建过程做归档。这两天集中在技术资料维护,未改动压缩和解压主流程。
2026-08-04:清理调试输出
注释掉压缩/解压链路中残留的 DEBUG 输出(BinaryStandardLoader、BinaryStandardWriter、HeaderWriter、CompressionLoop),避免高频打印阻塞主流程。同步更新技术文档。
2026-09-03:链接标准、版本闸门与工程重组
归档格式新增三种 Windows 链接条目:文件符号链接、目录符号链接与 Junction,标识符分别为 4、5、6。链接正文只保存名称与链接自身记录的原始目标路径,不解析目标,外部目标和悬空链接都作为普通元数据保存;解压在文件和目录恢复完成后统一重建链接。版本号随之由 0 升到 1,loadHeaderStandard 在魔数校验后增加版本校验,旧包在入口直接报 Unsupported archive version。
修复两类问题:首个 16KB 目录块恰好被塞满时被忽略;长度超过 260 字符的路径在 std::filesystem 与 GUI/CLI 混合链路下不稳定,改为用自定义工具部分代替 filesystem。移除旧 Linux 符号链接的预留逻辑。
FlagType 底层类型由 char 改为 uint8_t,枚举值从 ASCII '0'~'4' 改为数值 0~4,全仓引用均为符号形式、读写自动同步,并在 FLAG_SIZE 处加 static_assert。同时修复 AES 模块三处缺陷:providers 数组越界、从未赋值的死成员 aesKey、AesEncryption 中的无效 resize。
工程侧新增独立单元测试工程,使用 MinGW、不依赖 Qt;新增 CLI 验收工具 tool_archivebaseline,提供固定种子样本生成与 compress、decompress、roundtrip、verify 四类子命令。仓库结构把构建与测试合并为根目录 BuildTest/,GUI 目录更名 SFC_GUI,CompressorFileSystem 拆分为 Commons、DataIO、ArchiveFormat、Strategy 四个模块,非代码资产统一放在 DevFiles。
2026-09-04~06:AES 加固与写路径拆分
AES 安全加固:取缔裸指针,密钥与轮密钥用 SecureZeroMemory 擦除,更多类引入状态枚举取代 int。
写路径按三阶段拆分收尾:CatalogFinalizer 统一目录区收尾,先回填处理后大小的槽位、再原地加密,次序固定在类内;BinaryStandardLoader 纯读化,删掉 fstreamForRefill 与 encryptHeaderBlock,目录块位置表改由 takeBlockSpans() 移交;DataExporter 改为纯追加,删掉逐块 seek 回补,块长直写真实值。零字节验收:pack 与 huffman 两种模式的输出与拆分前逐字节一致。
运行期类型拆分:RuntimeLibrary.h 收纳 Y_flib::Runtime 子命名空间,放 DataBlock 与三个枚举等;FileLibrary.h 只保留磁盘格式类型,using 再导出以兼容约 220 处旧写法。
2026-09-07:v2.2.0 多线程流水线
压缩全程改为专职读线程、N 个计算工人、专职写线程的三段流水线,N 取 hardware_concurrency,取不到退 4。CompressionLoop 重写为总指挥,采用集中式关闭协议:join 读 → 关任务队列 → join 工人 → 关结果队列 → join 写 → CatalogFinalizer 收尾 → 关池;错误与取消路径同序收口后统一重抛首异常。
新增两个并发组件。SafeQueue.h 是模板化管程队列,析取等待、合取退出、关后拒绝;WriteSorter.h 按区段连续性给乱序到达的块定序,用右值化去掉整块拷贝,takeInOrder 自理刷出编排。消息协议收敛为 PipelineMessage 单结构加 kind 标签,区分 Block 与 Settlement,块与文件结算共用全局递增序号,槽偏移随结算消息直送写线程,原先读写两侧对账单加收尾 zip 的设计取消。六个 UML 类图同期全部重绘。
实测 HuffmanAES 模式、真实数据、同输入对照:大文件压缩 6.9 倍、长路径 3.6 倍、极端小文件 1.8 倍。解压侧随后以同构方式接入流水线,FileStart 占号开启输出文件,每块输出上限由读线程按 min(BUFFER_SIZE, 剩余) 预计算,把串行的跨块累计状态拆成无依赖的每任务参数;数据区用专用只读流纯顺序读,文件边界按 compressedSize 记账。解压吞吐:正常文件 24.1 → 126.2 MiB/s,5.2 倍;长路径 19.7 → 64.3 MiB/s,3.3 倍;极端小文件 1,135 → 834 文件/秒,回退到 0.74 倍,原因是同步开销摊不平微型计算,对策是调度合批。验收:pack 与 huffman 模式 711 文件、AES 带密码 712 文件往返逐字节一致。
2026-09-11:v2.2.1 内核提速
Huffman 编码:符号编码表由 unordered_map<unsigned char, CharData> 改为平坦 256 项数组,即 uint64_t code[256] 加 len[256],消掉每输入字节 3~4 次哈希探查与逐符号的堆上 vector 指针追逐;位合并由逐位 byte = (byte << 1) | bit 改为 64 位位缓冲整码字合并、按字节批量冲刷。单线程 8MB 块编码 63.2 → 471.1 MB/s。
Huffman 解码:改为 canonical 码,码字按码长与符号值升序连续分配,解码走 12 位主表 4096 项查表,码长超过 12 位的符号回退为逐位还原,取代原先每输入字节展开成 8 元素 vector 再逐位走树的做法。解码 91.3 → 236.8 MB/s。查表解码有适用边界,平均码长 1.80 bit 的极端偏斜数据上回退到 0.75 倍,因为极短码下固定每符号开销大于走树成本。
码长表取代整树序列化:treeToPlatUchar 与 spawnTree 改为 codeTableToPlatUchar 与 spawnCodeTable,序列化为 'L' 加最大码长加 256 项码长,共 258 字节,原先每节点两字节的整树序列化满字母表约 1023 字节。解压侧不再重建树,只需码长表即可还原码字,PathStack::writeCode 相应简化为只记码长。
AES 换标准实现:原自研 AES-128 CFB 核心的 MixColumns 混合轴有误,对同一行跨列混合,标准 AES 是对同一列。实测 128 例单 bit 翻转的密文差异全部局限在同一行,标准 AES 为 128/128 跨行,即状态矩阵四行独立演进、不满足分组密码的雪崩判据,密文与标准 AES 不互通、也没有硬件加速路径。改为 Windows CNG 的标准 AES-128-CTR,密钥流由 ECB 批量加密计数器块生成,实测 CNG 原生 CTR 本机不支持,CNG CFB 既不标准又不走硬件。加解密 62.8 与 62.1 → 1261.5 与 1279.6 MB/s,IV 仍为 16 字节前置,字节开销不变。
LTO 实装:BuildTest/CMakeLists.txt 与 BuildTest/tests/CMakeLists.txt 为 Release 开启 -flto,归档器改用 gcc-ar 与 gcc-ranlib 以消除 LTO 对象告警。
归档格式版本升到 3,低于 3 的归档一律拒绝。tool_archivebaseline 的 compress 与 compressdir 增加 huffman-aes 模式,端到端加密路径首次纳入验收。
整体吞吐对照,同一份 13.47 GiB、45,390 个文件的真实数据:压缩 254.3 MiB/s、解压 325.1 MiB/s,相对单线程版本分别是 9.78 与 9.91 倍。验收:test_huffman 115、test_aes 186、test_bufferpool 22、test_flagtype 36 全通过,test_safequeue 与 test_writesorter 全通过,端到端往返 8/8 文件逐字节一致。
结果
从 AES 算法实验到完整桌面归档工具。处理的问题:AES-128 加密、Huffman 编码表与解码表、BFS 目录遍历与逻辑根目录、目录块边界、目录恢复、Huffman 单字符边界、UTF-8 编码统一、GUI 线程模型与进度节流、策略模式重构、Qt 静态链接与单文件发布。
后半段重心转向吞吐:压缩与解压全程跑在三段流水线上,队列、定序器与缓冲池三个并发组件把计算和 I/O 重叠起来;编解码内核换成平坦符号表加 64 位位缓冲、canonical 码加 12 位查表解码和码长表,AES 从自研 CFB 换成走 AES-NI 的标准 AES-128-CTR。整体吞吐相对单线程版本压缩 9.78 倍、解压 9.91 倍。当前瓶颈已不在编解码,而在逐文件读写的串行读写路径。
部分信息可能已经过时
粤公网安备44011102484817号