# 新app得推倒重来了

**URL:** <https://forum.freemdict.com/t/topic/37083>\
**Category:** 闲聊吹水\
**Created:** [2025 年3 月 6 日 08:01 UTC](https://forum.freemdict.com/t/topic/37083 "2025-03-06T08:01:29Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

作者： ![midzuki\_yuka](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/midzuki_yuka/32/83965_2.png) [@midzuki\_yuka](https://forum.freemdict.com/u/midzuki_yuka)\
发布日期： [2025 年3 月 6 日 08:01 UTC](https://forum.freemdict.com/t/topic/37083/1 "2025-03-06T08:01:29Z")

</div>

前情提要：

> [@打算用swiftui搓个新词典软件出来](https://forum.freemdict.com/t/topic/35885/):
>
> 2.18：大进展，以[next-gen-dictionary-standard/Specification.md at main · freemdict/next-gen-dictionary-standard · GitHub](https://github.com/freemdict/next-gen-dictionary-standard/blob/main/Specification.md) 为蓝本改进了数据库结构，支持自定义ztsd压缩字典和读取压缩后的数据。 现在制定的结构大概是这样的： metadata 表 - 词典基础信息 id: 主键 key: …

真用上sqlite才发现为什么自研格式这么香了。用sqlite的话，大批量显示headline（查词的时候显示在左侧边栏的词头，或者说是（見出し））性能特别差。

现在转去自研格式了，正好有这个项目可以借鉴：[GitHub - golddranks/monokakido: A Rust library for parsing and interpreting the Monokakido dictionary format. Full test coverage and efficient implementation with minimal dependencies.](https://github.com/golddranks/monokakido)

今天刚搞懂他的.headlinestore怎么组织的，实现了读取。

 ![image](https://forumcdn.freemdict.com/uploads/default/original/3X/6/a/6a041f330426733011b184154878a202f95a44e0.png)

非常精巧的格式：

- 文件头部包含魔数、记录数量和关键偏移量
- 固定大小的记录结构（0x18字节）
- 文本和数据的偏移量索引

怪不得一次显示几十万条都是毫秒级的…

---

<div class="post-metadata">

作者： ![midzuki\_yuka](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/midzuki_yuka/32/83965_2.png) [@midzuki\_yuka](https://forum.freemdict.com/u/midzuki_yuka)\
发布日期： [2025 年3 月 6 日 08:06 UTC](https://forum.freemdict.com/t/topic/37083/2 "2025-03-06T08:06:11Z")

</div>

@last_idol  
at下大佬，你觉得自研二进制词典格式怎么样？

---

<div class="post-metadata">

作者： ![amob](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/amob/32/14630_2.png) [@amob](https://forum.freemdict.com/u/amob)\
发布日期： [2025 年3 月 6 日 08:49 UTC](https://forum.freemdict.com/t/topic/37083/3 "2025-03-06T08:49:59Z")

</div>

不少词典格式，都这个结构的，一个索引表记录大小和偏移，固定大小分块压缩和读取。技术原理简单，所以啥公司都能写出来。优化大小和读取速度主要在于算法的选择。比如安卓app一般直接用c++写native库，java效率不行。没有算法和汇编基础用ai辅助编程的话，还是别折腾性能吧。

---

<div class="post-metadata">

作者： ![amob](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/amob/32/14630_2.png) [@amob](https://forum.freemdict.com/u/amob)\
发布日期： [2025 年3 月 6 日 09:05 UTC](https://forum.freemdict.com/t/topic/37083/4 "2025-03-06T09:05:51Z")

</div>

比起索引的快速检索，一般人更能感知到词典内容的展现速度，goldendict众人共创的基于c++的项目，都有人嫌弃词典一多就显示太慢。真要极致的性能，肯定是直接舍弃html，杂七杂八组件太多，一般人都知道浏览器性能开销多大，有的人用electron展示html，性能天生落后人一截。但是html功能太强大，存储词典内容也方便，展示效果美观，谁会不用呢。

---

<div class="post-metadata">

作者： ![midzuki\_yuka](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/midzuki_yuka/32/83965_2.png) [@midzuki\_yuka](https://forum.freemdict.com/u/midzuki_yuka)\
发布日期： [2025 年3 月 6 日 09:06 UTC](https://forum.freemdict.com/t/topic/37083/5 "2025-03-06T09:06:42Z")

</div>

话是这么说的没错。  
monokakido也没什么特别厉害的算法啊，就是二分查找page id item id。

---

<div class="post-metadata">

作者： ![amob](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/amob/32/14630_2.png) [@amob](https://forum.freemdict.com/u/amob)\
发布日期： [2025 年3 月 6 日 09:09 UTC](https://forum.freemdict.com/t/topic/37083/6 "2025-03-06T09:09:10Z")

</div>

你逆向过app了？

---

<div class="post-metadata">

作者： ![midzuki\_yuka](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/midzuki_yuka/32/83965_2.png) [@midzuki\_yuka](https://forum.freemdict.com/u/midzuki_yuka)\
发布日期： [2025 年3 月 6 日 09:10 UTC](https://forum.freemdict.com/t/topic/37083/7 "2025-03-06T09:10:45Z")

</div>

我贴的那个github链接里的rust项目读取headline的部分是todo，所以逆向过了。

---

<div class="post-metadata">

作者： ![amob](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/amob/32/14630_2.png) [@amob](https://forum.freemdict.com/u/amob)\
发布日期： [2025 年3 月 6 日 11:04 UTC](https://forum.freemdict.com/t/topic/37083/9 "2025-03-06T11:04:01Z")

</div>

headline解析别人早做完了吧。我以前没运行过，今天试了下可以用。

 ![image](https://forumcdn.freemdict.com/uploads/default/original/3X/a/f/af278e75fba9fec94d95bfdf18eed402653f8690.png)

---

<div class="post-metadata">

作者： ![amob](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/amob/32/14630_2.png) [@amob](https://forum.freemdict.com/u/amob)\
发布日期： [2025 年3 月 6 日 11:08 UTC](https://forum.freemdict.com/t/topic/37083/10 "2025-03-06T11:08:08Z")

</div>

一晃都两年了，都被弃坑了。stephenmk把jitenbot和monokakido都删库了，2024年问了这位他说没精力弄monokakido解析了。

> [@【小学館】例解学習国語辞典［第九版］](http://forum.freemdict.com/t/topic/18491/50):
>
> [https://github.com/stephenmk/jitenbot](https://github.com/stephenmk/jitenbot) [GitHub - golddranks/monokakido: A Rust library for parsing and interpreting the Monokakido dictionary format. Full test coverage and efficient implementation with minimal dependencies.](https://github.com/golddranks/monokakido)

> [@【小学館】例解学習国語辞典［第九版］](https://forum.freemdict.com/t/topic/18491/51):
>
> 虽然 golddranks 是 monokakido 这个库的原作者，但是 stephenmk 的分支目前更有用一些。 [stephenmk/monokakido: A Rust library for parsing and interpreting the Monokakido dictionary format. Full test coverage and efficient implem…](https://github.com/stephenmk/monokakido)

---

<div class="post-metadata">

作者： ![midzuki\_yuka](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/midzuki_yuka/32/83965_2.png) [@midzuki\_yuka](https://forum.freemdict.com/u/midzuki_yuka)\
发布日期： [2025 年3 月 6 日 11:15 UTC](https://forum.freemdict.com/t/topic/37083/11 "2025-03-06T11:15:44Z")

</div>

你这是.keystore吧。.headlinestore没有前缀/长度/后缀索引。

---

<div class="post-metadata">

作者： ![amob](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/amob/32/14630_2.png) [@amob](https://forum.freemdict.com/u/amob)\
发布日期： [2025 年3 月 6 日 11:17 UTC](https://forum.freemdict.com/t/topic/37083/12 "2025-03-06T11:17:16Z")

</div>

不太了解，你给的图不太明确，我也没看懂，那应该我理解错了。

---

<div class="post-metadata">

作者： ![midzuki\_yuka](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/midzuki_yuka/32/83965_2.png) [@midzuki\_yuka](https://forum.freemdict.com/u/midzuki_yuka)\
发布日期： [2025 年3 月 6 日 11:19 UTC](https://forum.freemdict.com/t/topic/37083/13 "2025-03-06T11:19:08Z")

</div>

铁定是.keystore，因为要先通过.keystore的索引获取pageid和itemid然后在.headlinestore找到这两个id对应的标题。  
如果没有itemid，就返回整页，有itemid就跳到页面对应位置（估计是content.rsc里面封装的html有锚点。

---

<div class="post-metadata">

作者： ![midzuki\_yuka](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/midzuki_yuka/32/83965_2.png) [@midzuki\_yuka](https://forum.freemdict.com/u/midzuki_yuka)\
发布日期： [2025 年3 月 6 日 11:20 UTC](https://forum.freemdict.com/t/topic/37083/14 "2025-03-06T11:20:53Z")

</div>

你看headline.rs里面那个todo:就是了，这个没写完。

---

<div class="post-metadata">

作者： ![amob](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/amob/32/14630_2.png) [@amob](https://forum.freemdict.com/u/amob)\
发布日期： [2025 年3 月 6 日 11:29 UTC](https://forum.freemdict.com/t/topic/37083/15 "2025-03-06T11:29:04Z")

</div>

`dbg!("hmm", &e[..100]); // TODO: clean this up`  
话说这个问题你解决了吗，有的keystore好像格式不一样？在 Planned to support 列表里的。

 ![image](https://forumcdn.freemdict.com/uploads/default/original/3X/c/b/cb2d7a8058ac190f14886caecf57cf293394500d.png)

---

<div class="post-metadata">

作者： ![midzuki\_yuka](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/midzuki_yuka/32/83965_2.png) [@midzuki\_yuka](https://forum.freemdict.com/u/midzuki_yuka)\
发布日期： [2025 年3 月 6 日 11:36 UTC](https://forum.freemdict.com/t/topic/37083/16 "2025-03-06T11:36:43Z")

</div>

keystore怎么建索引的我还没研究透，这个我也不太清楚。不过不太像是有多种形式的keystore。今天晚上用hopperdissembler研究一下。

---

<div class="post-metadata">

作者： ![amob](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/amob/32/14630_2.png) [@amob](https://forum.freemdict.com/u/amob)\
发布日期： [2025 年3 月 6 日 11:38 UTC](https://forum.freemdict.com/t/topic/37083/17 "2025-03-06T11:38:41Z")

</div>

不是听说已经加密了吗？你在用老的应用逆向吗？

---

<div class="post-metadata">

作者： ![midzuki\_yuka](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/midzuki_yuka/32/83965_2.png) [@midzuki\_yuka](https://forum.freemdict.com/u/midzuki_yuka)\
发布日期： [2025 年3 月 6 日 11:40 UTC](https://forum.freemdict.com/t/topic/37083/18 "2025-03-06T11:40:05Z")

</div>

？我读取.headlinestore的.py就是靠逆向现在的app写出来的啊  
加密了吗？不清楚。

---

<div class="post-metadata">

作者： ![amob](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/amob/32/14630_2.png) [@amob](https://forum.freemdict.com/u/amob)\
发布日期： [2025 年3 月 6 日 11:40 UTC](https://forum.freemdict.com/t/topic/37083/19 "2025-03-06T11:40:59Z")

</div>

那就是只加了校验？格式没变？

> [@请求物书堂加密前的安装包](https://forum.freemdict.com/t/topic/23152/6):
>
> mac arm版物书堂在tg群里有旧版dmg，好像是1.2.36版。x86我的目前是1.2.38。

> [@已找到物书堂macOS版字典的储存路径 寻求提取字典内容的方法](https://forum.freemdict.com/t/topic/12025/17):
>
> update 2022.~11: 物書堂更改了词典路径变成了 /Users/用户名/Library/Group Containers/group.jp.monokakido.Dictionaries/Library/Application Support/com.dictionarystore/dictionaries/（有点ios那味了 如果是之前下载过的词典则仍保留在旧路径中 play_button 以下是一…

---

<div class="post-metadata">

作者： ![midzuki\_yuka](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/midzuki_yuka/32/83965_2.png) [@midzuki\_yuka](https://forum.freemdict.com/u/midzuki_yuka)\
发布日期： [2025 年3 月 6 日 11:50 UTC](https://forum.freemdict.com/t/topic/37083/20 "2025-03-06T11:50:58Z")

</div>

切换了一下旧版app，确实有几部读不出来…  
但是我读取headlinestore那个代码确实也是靠逆向新版app写出来。可能歪打正着了…

---

<div class="post-metadata">

作者： ![MeigenChou](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/meigenchou/32/90024_2.png) [@MeigenChou](https://forum.freemdict.com/u/MeigenChou)\
发布日期： [2025 年3 月 6 日 11:52 UTC](https://forum.freemdict.com/t/topic/37083/21 "2025-03-06T11:52:09Z")

</div>

正文早在前年就已经加密了…至于词头和索引可以说格式变了也可以说没变。headlinestore和keystore也是统合APP后才新弄的格式（这其中可能有稍微修改过数据结构），其实还有更早的不是这两个扩展名的文件。索引文件估计加密可能性不大，物书堂连压缩都没做，为了就是快速查找词条秒出结果。当然正文加密也不是一点办法没有，起码还能用传统操作（比如按键精灵…

[下一页](https://forum.freemdict.com/t/topic/37083.md?page=2)
