# Readmdict解析错误

**URL:** <https://forum.freemdict.com/t/topic/45542>\
**Category:** 技术交流与词典编修\
**Created:** [2026 年11 月 11 日 23:01 UTC](https://forum.freemdict.com/t/topic/45542 "2026-11-11T23:01:26Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

作者： ![feiwu](https://forumcdn.freemdict.com/letter_avatar_proxy/v4/letter/f/f17d59/32.png) [@feiwu](https://forum.freemdict.com/u/feiwu)\
发布日期： [2026 年11 月 11 日 23:01 UTC](https://forum.freemdict.com/t/topic/45542/1 "2026-11-11T23:01:27Z")

</div>

目前只遇到一个词典触发。

问题mdx供各位研究：  
[疑难字三考.mdx](https://forum.freemdict.com/uploads/short-url/2RZpOJ0MMhoN56fieZV4YJ3KTjm.mdx) (25.0 KB)

```auto
Traceback (most recent call last):
  File "c:\Users\admin\Desktop\new\xwang-mdict-analysis-927f91a5746b\readmdict.py", line 737, in <module>
    mdx = MDX(args.filename, args.encoding, args.substyle, args.passcode)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\admin\Desktop\new\xwang-mdict-analysis-927f91a5746b\readmdict.py", line 660, in __init__
    MDict. __init__ (self, fname, encoding, passcode)
  File "c:\Users\admin\Desktop\new\xwang-mdict-analysis-927f91a5746b\readmdict.py", line 115, in __init__
    self._key_list = self._read_keys()
                     ^^^^^^^^^^^^^^^^^
  File "c:\Users\admin\Desktop\new\xwang-mdict-analysis-927f91a5746b\readmdict.py", line 365, in _read_keys
    return self._read_keys_v1v2()
           ^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\admin\Desktop\new\xwang-mdict-analysis-927f91a5746b\readmdict.py", line 448, in _read_keys_v1v2
    key_block_info_list = self._decode_key_block_info(key_block_info)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\admin\Desktop\new\xwang-mdict-analysis-927f91a5746b\readmdict.py", line 197, in _decode_key_block_info
    assert(key_block_info_compressed[:4] == b'\x02\x00\x00\x00')
AssertionError

```

将

```auto
        if self._version >= 2:
            # zlib compression
            assert(key_block_info_compressed[:4] == b'\x02\x00\x00\x00')
            # decrypt if needed
            if self._encrypt & 0x02:
                key = ripemd128(key_block_info_compressed[4:8] + pack(b'<L', 0x3695))
                key_block_info_compressed = key_block_info_compressed[:8] + _fast_decrypt(key_block_info_compressed[8:], key)
            # decompress
            key_block_info = zlib.decompress(key_block_info_compressed[8:])
            # adler checksum
            adler32 = unpack('>I', key_block_info_compressed[4:8])[0]
            assert(adler32 == zlib.adler32(key_block_info) & 0xffffffff)

```

替换为

```auto
        if self._version >= 2:
            # 块头 4 字节是压缩方式（小端）：02 00 00 00 = zlib（标准写法），
            # 00 00 00 00 = 不压缩。官方 MdxBuilder 对 Encrypted=2（禁止导出）
            # 的词典写后者，旧实现只认前者，于是报「魔数不匹配」。
            # 后面仍有 adler32 校验兜底，放宽不会误放行损坏文件。
            head = key_block_info_compressed[:4]
            if head == b'\x02\x00\x00\x00': use_zlib = True
            elif head == b'\x00\x00\x00\x00': use_zlib = False
            else: raise ValueError("MDX key block info 魔数不匹配")
            if self._encrypt & 0x02:
                key = ripemd128(key_block_info_compressed[4:8] + pack(b'<L', 0x3695))
                key_block_info_compressed = key_block_info_compressed[:8] + _fast_decrypt(key_block_info_compressed[8:], key)
            payload = key_block_info_compressed[8:]
            key_block_info = zlib.decompress(payload) if use_zlib else payload
            adler32 = unpack('>I', key_block_info_compressed[4:8])[0]
            actual = zlib.adler32(key_block_info) & 0xffffffff
            if adler32 != actual:
                raise ValueError(f"MDX key block info 校验失败 (adler32): 期望 {adler32:#x}, 实际 {actual:#x}")

```

可以解决。

AI分析如下：

**文件没问题，是解析器的兼容性限制** 。​ 你用官方工具打包的 2.0 + `Encrypted=2`（禁止导出），这类词典的 key block info 用的是「 **无压缩** 」写法，而项目把魔数硬编码成了「zlib」。

| 线索 | 结论 |
| --- | --- |
| 740 处 0d 92 01 3d | 我算过 zlib.adler32(struct.pack(‘\>QQQQQ’,1,1829,80,88,10048)) = 0x0d92013d，正是 40 字节索引头的校验和 → 布局完全标准，偏移没错 |
| 88 = 80 + 8 | 压缩后只比解压后多 8 字节头，说明根本没有 zlib 压缩 |
| [4] 在 832 找到的 02 00 00 00 | 744+88=832，是 key block 的块头（诊断脚本误判，已修正说明） |
| 744 处 00 00 00 00 | 块头 compression\_method=0（不压缩），不是损坏 |
| 解密后 [8:16] = 00 00 00 00 00 00 07 25 | 大端 = 1829，正好等于 num\_entries → 密钥 ripemd128([4:8]+0x3695) 和「只解密 [8:]」项目原本都是对的，唯独解压方式猜错了 |

---

<div class="post-metadata">

作者： ![chigre3](https://forumcdn.freemdict.com/letter_avatar_proxy/v4/letter/c/47e85d/32.png) [@chigre3](https://forum.freemdict.com/u/chigre3)\
发布日期： [2026 年11 月 12 日 06:27 UTC](https://forum.freemdict.com/t/topic/45542/2 "2026-11-12T06:27:59Z")

</div>

提交一个 PR 吧~ ；）

---

<div class="post-metadata">

作者： ![feiwu](https://forumcdn.freemdict.com/letter_avatar_proxy/v4/letter/f/f17d59/32.png) [@feiwu](https://forum.freemdict.com/u/feiwu)\
发布日期： [2026 年11 月 12 日 11:27 UTC](https://forum.freemdict.com/t/topic/45542/3 "2026-11-12T11:27:49Z")

</div>

github仓库已归档，bitbucket没有账号，我尝试邮箱联系一下 **Xiaoqiang Wang**
