1636 字
8 分钟
SFC 开发日志(二):压缩 / 解压、目录恢复与首个 CLI 版本

项目仓库: Gitee | GitHub

依赖部分文件头的实现、目录块和偏移量逻辑实现。开始编写数据区的写入、目录恢复、解压读取和命令行版本,并且构建发布版。

上一篇:SFC 开发日志(一)

2025 年 12 月 1 日到 2025 年 12 月 2 日:数据块表示#

压缩模块、加密模块、读取器DataLoader和导出器DataExporter统一使用 DataBlock = std::vector<uint8_t>。压缩模块与文件流解耦。协议层、算法层和导出层通过同一类型传递数据。

整理Y_flib 命名空间的初始版。HeaderLoader 分块读取采用迭代器混合状态机模式处理生产消费耦合。目录、树数据、压缩数据。模块只接收字节数据,不关心上游来自文件、目录项还是算法中间产物。

2025 年 12 月 3 日到 2025 年 12 月 6 日:HeaderWriter 扩展与压缩侧联通#

HeaderWriter v0.1.5 继续扩展。目录协议增加符号链接标准,格式为链接名长度、目标路径长度、链接名和目标路径。(目前随跨平台方案难产废弃) 目录块和数据块都引入 IV 字段。Separated 标准的职责从块边界标记扩展为“块大小 + IV + 分块标识”。

| 标志 '4' | 链接名长度(4B) | 目标路径长度(4B) | 链接名 | 目标路径 |

IV 协议统一放在块分割协议开头。目录块、树数据、压缩数据都通过分割标准记录 IV。读取侧先读标准,再按 IV 决定是否解密(早期按浮点精度随机数生成器随机不到0判断,后期已经改为依照策略头判断整体是不是经过AES加密)。此时写入器负责输出目录结构、回读解压侧所需块信息。

输出文件流程:写文件头、写目录块、读刚刚写的目录块、按块处理、目录块加密(此时是耦合的)、写进处理后块、回填大小。HeaderWriterEntryProcessorDataExporter 与压缩模块围绕同一个输出文件(协议化目录)工作。

2025 年 12 月 8 日到 2025 年 12 月 9 日:AES 模块补齐#

AES 从独立算法代码转成归档流程模块。密钥派生仍然使用 SHA-256 的前 16 字节,密钥扩展生成 44 个轮密钥字,主体保持标准 10 轮 AES-128。添加乘法表 GF_MUL_2GF_MUL_3GF_MUL_9GF_MUL_11GF_MUL_13GF_MUL_14 ,利用缓存命中减少运行时 GF(2^8) 乘法计算耗时,实测目前软件AES方案增快80%以上。

2025 年 12 月 10 日到 2025 年 12 月 12 日:BFS 目录遍历与逻辑根目录#

EntryProcessor BFS 目录遍历方案。输入文件和输入目录先挂到逻辑根目录下,再由队列按层序遍历。目录项进入 entryQueue,子目录继续入队,文件项写入文件标准。目录块每写满 16KB,就插入一条分割标准,把当前块大小和 IV 写入协议。

void EntryProcessor::flowScanner(...)
{
// 1. 写入逻辑根节点
// 2. 处理用户指定的文件/目录列表
// 3. 循环从队列取出目录,处理其内容
// 4. 遇到子目录时加入队列继续遍历
}

BFS 目录遍历直接服务目录恢复。解压器不需要外部目录描述文件,只按目录标准和 childCount 推进队列,就能还原父目录、子目录和同层兄弟项的关系。协议为处理多个文件、文件夹逻辑根目录(本质森林合成一颗树)。利用逻辑根目录提供一个根节点(无序)。

2025 年 12 月 13 日到 2025 年 12 月 17 日:解压流程#

解压流程主体是 BinaryStandardLoader。类内部维护 fileQueueentryQueuedirectoryQueueReadyblockPosition,分别负责待解压文件项、目录项上下文、目录恢复顺序和目录块回写位置。读取器先打开归档文件,验证魔数,读取文件头,定位到 directoryOffset,逐块读取目录块,再把数据交给 EntryParser解析。

读取 .sy 文件
-> 验证魔数
-> 跳转到目录块偏移
-> 按需解密目录块
-> 解析文件队列和目录队列
-> 创建目录结构
-> 逐块读取数据区
-> 解密 Huffman 树
-> 重建 Huffman 树
-> 解密压缩数据
-> Huffman 解码
-> 写回原文件

EntryParser 解析目录标准和文件标准后,把文件条目压入 fileQueue,把目录路径压入 directoryQueueReadyDecompressionLoop 先创建目录,再根据文件条目进入数据区。文件条目中的第二字段在压缩场景承担偏移量语义,在解压场景承担 compressedSize 语义。

2025 年 12 月 18 日到 2025 年 12 月 25 日:工程整理与 CLI 交互#

工程整理与主流程开发。huffman的std::map 替换为 std::unordered_map,整理优化CLI相关代码(GUI版本已删除的main.cpp)。

采用了耦合设计:目录块、树数据、压缩数据、加密过程全部写进压缩 / 解压主循环。

2025 年 12 月 30 日到 2025 年 12 月 31 日:Huffman 单字符边界问题#

单字符输入的协议边界:数据块全部由同一个字节组成时,Huffman 树只有一个叶子节点,常规的构造方式失效。树生成失败后,编码和回读都会随之失效。

处理方式是给单字符场景固定一位编码。树节点数量为 1 时,编码直接写成 {0},长度记为 1。压缩侧仍能生成树数据和编码数据,解压侧也按同一规则恢复。单字符文件和单字符数据块纳入标准压缩 / 解压流程。

if (countLeaves(treeroot) == 1) {
hashtab[onlyChar].code = {0};
hashtab[onlyChar].codelen = 1;
}

2026 年 1 月 1 日到 2026 年 1 月 6 日:首个 CLI 预览版本#

v1.0.0 Preview 首个release。实现了CLI版本的加密压缩与解压全流程。修复数据区解码和单字符边界问题。

预览版仍有稳定性修正项:目录偏移量类型统一为 uint64_t,目录缓冲区大小固定为 16KB,部分 constexpr const 历史写法被清理,项目说明与 README 同步补全。归档体积超过 4GB 时,32 位偏移量没有可用空间,因此偏移量类型固定为 uint64_t

结果#

主逻辑完成,引入目录遍历与逻辑根目录,BinaryStandardLoaderEntryParser 把目录恢复纳入主流程,Huffman 单字符边界bug修复,发布CLI 形式的压缩与解压工具。


下一篇:SFC 开发日志(三):CLI 稳定化、Qt GUI 与发布

SFC 开发日志(二):压缩 / 解压、目录恢复与首个 CLI 版本
https://www.yonagi.world/posts/sfc-dev-log-2/
作者
YONAGI
发布于
2026-04-29
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

封面
遠い日に想いを馳せて
Laplacian
封面
遠い日に想いを馳せて
Laplacian
0:00 / 0:00