事情得从 10 月 22 日下午说起。我在小区门口那家开了十几年的旧书店「文汇斋」翻箱底,店主老周从柜台底下拖出一个纸箱,说里面是他儿子去年搬走时留下的几块硬盘和一本 2011 年的《电脑爱好者》合订本。硬盘我没要,那本杂志我买了下来,翻到第 63 页时,看到一篇讲图库索引结构的老文章,作者署名是「沈立群」,文末留了个很短的脚本片段。我盯着那段代码看了大概两分钟,忽然想起自己硬盘里还留着老版49图库的一整套缓存文件。
那套缓存在我移动硬盘的 /bak/2019/img49 目录里,一共 47 万 3 千多条索引记录,缩略图 120×160 像素,文件名是按六位数字加字母后缀的方式编的。之前一直没动它,是因为我判断索引已经损坏到不可修复——打开后前 200 条正常,从第 201 条开始,缩略图全部指向同一张灰色占位图。这一次,我决定按沈立群那篇文章里的思路,重新做一遍校验。
第一步:先确认为什么会「吞条目」
晚上九点四十,我把那台 2013 年的华硕 X550C 打开,风扇响了大概十秒才稳定下来,屏幕亮度调到 60%。系统里装的是我去年为了跑旧脚本专门留下的一个分区,Python 版本停在 2.7,也没舍得升。我写了个不到 40 行的比对脚本,把索引文件按行读进来,统计每条记录里的校验位和缩略图实际文件的 MD5 是否对得上。结果跑完是 9 分 12 秒,有 31 万 8 千多条校验失败,失败率接近 67%。
这个数字比我想象的高。我原以为只是缩略图路径错了,但一路打印日志发现,问题出在记录之间的偏移量上——老版49图库在 2018 年前后换过一次缩略图的命名规则,从「纯数字」改成了「数字+字母后缀」,而那个时期的索引写入逻辑没有跟着改,导致后面每一条记录的读取位置都整体错开了一小段。偏移量累积起来,就是成片成片的灰块。这跟沈立群那篇文章里描述的情况几乎一模一样,他在文章末尾用了一句很克制的话:「偏移不修,图库看起来就像被谁偷走了。」
第二步:按校验位分段重建,而不是从头重排
从头重排 47 万条记录,在那台机器上至少得跑两个多小时,而且一旦中途断电,前面的工作全白做。我改用分段法:以每 5000 条为一个块,先算出块内记录的校验位分布,找到偏移开始的那条记录位置,再把该块后面的记录整体前移或后移对应字节数。这个办法的坏处是慢,好处是每完成一块就能落盘一次,断电也不会全丢。第一块跑完用了 1 分 47 秒,我把结果写进一个叫 fix_001.log 的文件里,重新打开时,前 5000 条缩略图里有 4987 条能正常显示。
整个过程里我做了三次对照。第一次拿 2019 年备份的原始文件做基准,检查块边界有没有被切错;第二次用一张我自己记得内容的图——编号 004912,是一张植物园温室的老照片——验证恢复出来的图像是不是原来那张;第三次是把恢复后的索引倒序读一遍,看看末尾那几百条有没有因为缓冲区问题被覆盖。三次对照都过了之后,我才敢说这套方法是站得住的。顺带说一句,如果你手上也有类似打不开的旧索引,先别急着换浏览器,浏览器打开网站39777 那篇里记过一次挺像的排查过程,思路可以互相参照。
第三步:把能对上号的条目单独抽出来
校验通过之后,我并没有把整个库直接导回去,而是先把能完整对上号的条目抽到一个独立目录里,一共 41 万 6 千多条,剩下的 5 万多条单独放在 /orphan 里等人工看。这个动作看起来只是整理,其实决定了后面能不能复现——抽出来的这批条目有完整的校验记录,下次再坏,也能很快定位到是从哪一块开始出问题的。我顺手用一个老版本的读取工具打开抽出来的样本,确认没有出现读取越界的情况,工具本身是从 477在线免费浏览器 那篇里的说明找下来的旧包。
抽条目的过程中还发现一件小事:有 1,204 条记录的缩略图文件名里带了一个当时不该出现的空格字符,Windows 下能读,放到另一个平台就报错。这批我单独做了重命名,规则是去掉空格、保留原六位编号。这件事没有出现在沈立群的文章里,是我自己碰上的,所以也不敢说对所有老版图库都通用。
沈立群在《电脑爱好者》2011 年第 9 期那篇《索引的偏移》里写:「修索引最难的不是改对一处,是改对一处之后,你还要有办法证明它是对的。」——沈立群,《索引的偏移》,《电脑爱好者》2011 年第 9 期,第 63 页
关于「恢复」这个词,我的一点私见
说实话,市面上很多号称「老版49图库恢复」的工具,被严重高估了。它们做的事情大多只是把索引文件另存一份、换个后缀再打开,真正的偏移问题一个都没碰,用户看到缩略图回来了一部分,就以为是恢复了。我这台旧本子跑出来的结果不算好看,67% 的失败率,修了三个晚上才把主体理干净,但每一条修好的记录我都能说清楚它是怎么被修好的。我认为判断一个恢复方案靠不靠谱,标准只有一个:它能不能告诉你哪一条没修好、为什么没修好。说不出来的,基本可以不用再试。
至于下载和使用的入口,我自己习惯从 四九图库应用下载 那页找旧版本的安装包,因为新版本对这套老索引的兼容性反而不如 2019 年那个版本。另外提醒一句,如果你在某个系统里打开恢复后的索引报编码错误,先去看 qq浏览器无法打开文件 里提到的文件头处理办法,我遇到的两次乱码都是那个原因,跟索引本身没关系。
写完这些已经快十二点了。灯还开着,旧本子的风扇还在响,但我心里挺踏实的——不是因为结果多漂亮,而是因为我终于能一条一条说清楚这 47 万条记录里,哪些回来了,哪些还躺在 /orphan 里等着。明天我打算把人工核对那 5 万多条的计划列出来,如果进度顺利,会再写一篇。