纯 MoonBit 实现的 7z 归档只读解包库:容器解析 + LZMA/LZMA2 解码内核(库本体零第三方依赖)
状态:0.1.0 开发中。已实现起始头校验、明文头解析、编码头(LZMA/LZMA2 压缩的头)解码、 条目表与端到端解包(COPY / LZMA1 / LZMA2)。 也就是说:bsdtar 或 7-Zip 生成的普通 7z(明文头或 LZMA/LZMA2 压缩头)都可以列目录并解出内容。
| 能力 | 状态 |
|---|---|
| 起始头 / 两处 CRC-32 / 边界校验 | ✅ |
| 明文头(kHeader):属性树、Folder/Coder、SubStreams、文件表 | ✅ |
| 编码头(kEncodedHeader):用 LZMA1/LZMA2 解出被压缩的头 | ✅ |
| 解包 coder:COPY(0x0) / LZMA1(0x030101) / LZMA2(0x21) | ✅ |
| 目录、空文件、非 ASCII(UTF-16)文件名、Solid 块、多子流 | ✅ |
| 过滤器链(BCJ/Delta 等前置 coder)、AES 加密、分卷、BCJ2、PPMd/BZip2/Deflate | ❌ 明确不做(报 Unsupported) |
| 包 | 覆盖范围 |
|---|---|
| TWISTY2Ynb/moonmspack | CAB / CHM / MSZIP / LZX(Microsoft 容器族) |
| aurora0x27/lzma-mbt、lin2077-zeming/moonxz | .xz / .lzma 单流格式的编解码 |
| moon7z(本项目) | 7z 归档容器:属性树、Folder/Coder 图、文件表、Solid 块与解包 |
moon add Sxy11112/moon7z # 作为依赖加入你的 MoonBit 项目fn demo(bytes : Bytes) -> Unit raise {
let z = @moon7z.SevenZ::open(bytes)
for e in z.entries() {
println(e.name + " " + e.size.to_string()) // 目录的 size 为 0,is_dir 为 true
}
let files = z.extract_all() // [ArchiveFile]:name + data
println(files.length().to_string() + " 个文件")
}
let z = @moon7z.SevenZ::open(bytes) // 校验签名、版本、两处 CRC-32 与偏移边界
// F1:起始头
let sh = z.start_header()
println(sh.minor) // 归档次版本号(bsdtar 写 0.3,官方写 0.4)
println(sh.absolute_offset()) // 头数据库在文件中的绝对起点
// 条目表与流信息
let entries = z.entries() // [Entry]:name / size / crc / is_dir
let streams = z.streams() // 打包位置与大小、Folder/coder 链、子流大小与 CRC
// 解包(COPY / LZMA1 / LZMA2)
let files = z.extract_all() // [ArchiveFile]:目录跳过,空文件为空 Bytes
let one = z.extract("a.txt") // 按名字取单个文件| 语料 | 压缩 | 说明 |
|---|---|---|
| two_text.7z / two_text_lzma1/2.7z | LZMA/LZMA2 | 编码头(0x17),供 F4/F5 |
| two_text_copy.7z | copy | 明文头,多文件 |
| one_file_copy.7z / tree_copy.7z | copy | 单文件;含目录条目(kEmptyStream) |
| empty_file_copy.7z | copy | 含 0 字节文件(kEmptyStream + kEmptyFile,非目录) |
| nested_copy.7z | copy | 嵌套目录 + 非 ASCII(UTF-16)文件名 |
| big_copy.7z | copy | 20 KB 文件(较大 packed 数据的切片与 CRC) |
| minimal_two_copy.7z | copy | 手工构造的最小两文件归档(libarchive 复核可读) |
# 列目录:每行 "<名字>\t<大小>\t<CRC32>"(目录的 size/crc 为 "-")
moon run --target js cmd/main -- list tools/corpus/two_text.7z
# 解包到目录(自动创建子目录)
moon run --target js cmd/main -- extract tools/corpus/tree_copy.7z /tmp/outpub suberror SevenZError {
Truncated(offset~ : Int64, need~ : Int64, actual~ : Int64)
BadSignature(found~ : String)
UnsupportedVersion(major~ : Int, minor~ : Int)
BadCrc(what~ : String, expected~ : Int64, actual~ : Int64)
Malformed(reason~ : String)
Unsupported(what~ : String)
LzmaCorrupt(reason~ : String)
}pub struct ByteReader {
data : Bytes
pos : Int
}pub struct Coder {
id : Int64
props : Bytes
num_in : Int
num_out : Int
}pub struct Crc32 {
table : FixedArray[Int64]
value : Int64
}pub struct StartHeader {
major : Int
minor : Int
next_header_offset : Int64
next_header_size : Int64
next_header_crc : Int64
}fn copy_range(data : Bytes, start : Int, end : Int) -> BytesInstall
Download zip纯 MoonBit 实现的 7z 归档只读解包库:容器解析 + LZMA/LZMA2 解码内核(库本体零第三方依赖)