标题: ZIP解压失败后的抢救 创建: 2024-05-20 00:00 更新: 链接: https://scz.617.cn/misc/202405200000.txt some.zip在压缩生成ZIP的过程中出现问题,有个文件数据有误: any.ext 具体来说,该文件如下字段出现异常: ZIPFILERECORD.frCrc 0xb5660da4 ZIPDIRENTRY.deCrc 0xb5660da4 若用7-Zip打开,对应CRC列的值。若用bkcrack查看,如下: $ bkcrack -L some.zip | findstr any.ext 519 None Store b5660da4 597137 597137 正常情况下,frCrc、deCrc相等,均对应单个文件解压后数据的CRC32。解压工具一 般会在解压每个文件时检查ZIP中记录的CRC32与实际解压后数据的CRC32是否匹配, 不匹配会告警,某些弱智解压工具遇此情况可能拒绝解压ZIP中其余正常文件。 7-Zip是成熟工具,但遇此情况亦有坑。在7-Zip GUI中拖放式析取目录时,若目录中 某文件CRC错,整个目录的拖放式析取会失败。非拖放式析取时,显式点选Extract, 则会尽最大努力解压ZIP。在资源管理器右键菜单中用7-Zip的各种Extract,同样尽 最大努力解压ZIP。问题在于,许多人习惯性GUI拖放式析取,就掉坑里了。 只要尽最大努力解压ZIP,可得绝大多数内容。 7-Zip GUI选中文件或目录,右键CRC,再CRC-32,若有CRC错,会直接显示对应条目; File->CRC->CRC-32,可对ZIP中每个文件进行CRC校验;拖放式析取失败时也会显示 CRC错的条目,但不如前两者划算。 7-Zip GUI中删除CRC错的文件,之后可进行拖放式析取。由于可强行解压,这招无实 际意义。 本例中异常any.ext的CRC32实际是0xa51482f7,强行解压后,单求CRC32可得。 最初没想起强行解压的茬,拖放式析取掉坑。想的是,临时修正frCrc、deCrc,规避 CRC错,至少析取其余文件。可用010 Editor套ZIPAdv.bt模板,找如下字段: record[i].frCrc dirEntry[i].deCrc 用7-Zip或bkcrack确认ZIP中文件均用Store模式存放,只是打包,并未压缩,所以 ZIPFILERECORD.frData[]保存的就是原始数据,此时可对之求CRC32。在010 Editor 中选中frData[],点选Tools->Check Sum (Ctrl-K),在算法中勾选CRC-32,计算并 显示CRC值,据此修正frCrc、deCrc。由于可强行解压,这招无实际意义。 Linux的zip工具有两个参数,号称可以"Fix the zip archive",一般用法是: zip -F bad.zip --out bad_fix.zip zip -FF bad.zip --out bad_fixfix.zip man手册中建议优先使用-F参数,未达目的时再用-FF参数。实测本例,-F未修正CRC 错,-FF结果更扯淡,不用也罢。