moonpar2

    Offline PAR2 recovery for small file sets

    Download zip
    Author
    Version
    0.1.0
    License
    MIT
    Last updated
    5 hours ago
    Downloads
    2

    No dependencies

    #MoonPar2

    MoonPar2 为同一目录中的文件创建 PAR2 恢复卷。备份中的文件丢失或部分损坏后,可以用恢复卷定位坏块,把完整文件写到一个新目录。也可以读取 par2cmdline 生成的索引和分卷。

    #构建和演示

    安装 MoonBit 工具链 和 Node.js 24。下面的命令在仓库根目录运行。最后一步需要 Python 3,只用于演示。

    moon build cmd/main --target js node _build/js/debug/build/cmd/main/main.js --help python examples/repair_demo.py

    演示在临时目录中生成两个小文件和恢复卷,删除 notes.txt,改坏 scan.bin 的最后一个字节,再将两份文件还原到新目录。成功时会看到两行 SHA-256 matches。

    #保护和修复自己的文件

    把编译好的 _build/js/debug/build/cmd/main/main.js 复制到工具目录,命名为 moonpar2.cjs。在待备份的文件夹中运行以下命令,将示例中的脚本路径替换为实际位置。

    node /path/to/moonpar2.cjs create photos.par2 scan.bin notes.txt node /path/to/moonpar2.cjs verify photos.par2 node /path/to/moonpar2.cjs repair restored photos.par2

    • 创建会在当前目录生成一个卷,包含文件清单、分块校验值和恢复块。默认写入四个恢复块,可用 create --recovery-blocks 8 photos.par2 scan.bin notes.txt 调整冗余(1 至 32 块)。卷名必须尚未被使用。
    • 校验从第一个卷所在目录读取源文件,逐个报告正常、缺失或损坏。退出码 0 表示全部正常,1 表示发现损坏或缺失,2 表示参数、输入格式或文件操作错误。
    • 修复先在内存中重建并验证所有文件,再写入指定的新目录。原始文件不会被覆盖。若磁盘写入中断,使用另一个新目录重试。
    • 对于官方工具生成的多个卷,显式传入需要的分卷,例如 repair restored set.par2 set.vol0+1.par2 set.vol1+2.par2。只有索引时仍可校验,但修复需要足够的独立恢复块。

    #使用场景

    • 归档交付。 把 ZIP 文件和目录清单一起生成恢复卷。收件人可以离线检查下载结果,修复局部损坏后重新打开 ZIP。
    • 找回误删的文件。 同一组中的小文件丢失时,从索引读回文件名及校验值,恢复块足够时将整组写到新目录。一个丢失的文件消耗的恢复块数等于文件大小除以块大小后向上取整。
    • 接入已有工具。 MoonBit 应用可以直接读取 par2cmdline 的索引和分卷,列出坏块或重建内容。使用 par2cmdline 的另一端也能修复 MoonPar2 生成的备份。

    #支持范围

    适合照片、扫描件、文档和中小型 ZIP 交付包。输入与修复结果在内存中处理。当前按固定偏移检查数据,不扫描重命名的文件或发生字节插入、删除后移位的文件。

    项目范围
    源文件最多 64 个非空普通文件,总计 64 MiB;单层目录,使用可移植的 ASCII 文件名
    分块不超过 4 MiB 的文件集默认使用 4 KiB 块;更大集合自动选择 32–256 KiB。读取时支持 4 字节的倍数,最大 256 KiB,最多 4096 个源块
    恢复数据读取最多 32 个不同的恢复块,所有输入卷合计最多 16 MiB
    运行环境核心库使用 MoonBit;命令行使用 Node.js 读写本地文件,无运行时网络服务

    对于正好 64 MiB 的集合,自动块宽为 256 KiB。8 个恢复块占约 2 MiB(另加元数据),可以补回最多 8 个丢失块,前提是相应的恢复方程线性独立。分散在多个块上的损坏会分别计数。

    #正确性验证

    MoonBit 应用可以直接使用 create、read_set、verify 和 repair,数据来自内存时无需调用命令行。运行 moon run examples/library --target js 可查看一个完整的调用示例。

    moon check --target js --deny-warn moon test --target js --deny-warn moon build cmd/main --target js --deny-warn python tests/interop.py --par2 /path/to/par2

    交叉测试使用 par2cmdline 1.4.0。两种工具分别创建恢复卷;随后同时改坏一个文件、删除另一个,分别用两个工具修复并比对原件 SHA-256。测试还覆盖恢复数据不足和输出路径已存在的情况。

    格式依据 Parity Volume Set Specification 2.0。命令行调用自己的 MoonBit 编解码实现;par2cmdline 仅用于交叉验证。许可证为 MIT。

    #复现容量边界

    运行 python tests/capacity.py --mib 64。脚本生成合计恰好 64 MiB 的 ZIP 和清单,校验后破坏 ZIP 中部并删除清单,再检查修复文件的 SHA-256 及 ZIP 内部 CRC。它还检查多一个字节时不会留下输出卷。传入 --par2 /path/to/par2 可用另一实现校验和修复同一组文件,再让 MoonPar2 读取对方按不同块宽生成的分卷并执行修复。脚本按命令报告耗时和 Node 进程峰值内存。

    FileStatus

    pub(all) struct FileStatus {
    name : String
    healthy : Bool
    missing : Bool
    damaged_slices : Array[Int]
    }

    RecoverySet

    type RecoverySet

    RecoverySet::names

    fn RecoverySet::names(self : RecoverySet) -> Array[String]

    RecoverySet::repair

    fn RecoverySet::repair(self : RecoverySet, files : Map[String, Bytes]) -> Array[(String, Bytes)] raise

    Rebuild a complete set in memory. No output is returned until every reconstructed file has passed its packet's whole-file checksum.

    RecoverySet::verify

    fn RecoverySet::verify(self : RecoverySet, files : Map[String, Bytes]) -> Array[FileStatus]

    MaxSourceBytes

    let MaxSourceBytes : Int

    MaxVolumeBytes

    let MaxVolumeBytes : Int

    create

    fn create(files : Array[(String, Bytes)], width? : Int, recovery_blocks? : Int) -> Bytes raise

    encode

    fn encode(blocks : Array[Array[Int]], exponent : Int) -> Array[Int]?

    read_set

    fn read_set(volumes : Array[Bytes]) -> RecoverySet raise

    recover

    fn recover(data : Array[Array[Int]?], exponents : Array[Int], parity : Array[Array[Int]]) -> Array[Array[Int]]?

    safe_name

    fn safe_name(name : String) -> Bool

    Powered by MoonBit

    Site sourceReport issueModulesSkillsBuild queueStatistics

    © 2026 mooncakes.io