下载了一个几十 MB 的压缩包,双击解压,报「文件已损坏或格式未知」。或者一张图片显示不出来,看图软件只说「无法打开」。
报错信息几乎从不告诉你哪里坏了。 但把文件拖进 Hex 二进制查看,几十秒就能分辨出是哪一类问题——而这决定了你接下来该重新下载、该换传输方式,还是该去找密码。
(本文只讲排查损坏。「这是个什么格式的文件」属于另一个问题,见 文件魔数速查。)
形态一:你下到的根本不是那个文件
这是最常见的一类,而且完全不是「损坏」。
看前几个字节的 ASCII 列:
| 开头字节 | ASCII | 说明 |
|---|---|---|
3C 21 44 4F 43 | <!DOC | HTML 页面 |
3C 68 74 6D 6C | <html | HTML 页面 |
7B 22 | {" | JSON 错误响应 |
服务端返回的不是文件,而是一个页面:登录页、防盗链拦截页、CDN 的 502 错误页、过期的网盘分享页。浏览器或下载工具照单全收,存成了 .zip。
更快的判据是文件大小:预期几十 MB,实际只有 3 KB——不用打开就知道了。
对策是回去看下载链接(要不要登录、Referer 对不对、链接过没过期),修文件是白费力气。
形态二:头部正常,尾部缺失——传输被截断
很多格式的关键结构在文件末尾,这就是「只看魔数不够」的原因。
| 格式 | 尾部标记 | 含义 |
|---|---|---|
| ZIP | 50 4B 05 06 | 中央目录结束记录(EOCD) |
| PNG | 49 45 4E 44 AE 42 60 82 | IEND 块 + 固定 CRC |
| JPEG | FF D9 | EOI 结束标记 |
25 25 45 4F 46 | %%EOF | |
| GZIP | 最后 8 字节 | CRC32 + 原始长度 |
以 ZIP 为例:EOCD 记录着包里有哪些文件、各自在什么偏移,而它在文件最末尾(无注释时是最后 22 字节)。截断丢掉尾部,解压程序就不知道包里有什么,于是报「不是有效的压缩文件」——尽管开头的 50 4B 03 04 好好的。
头对尾不对 = 截断。 常见成因:下载中断后续传出错、磁盘写满、进程被杀、网盘限速超时。
这类损坏本地修不了,缺的字节就是没有了,只能重新下载。
形态三:换行字节被改写——文本模式污染
这一类最有迷惑性,因为魔数往往仍然正确,文件看着完整。
成因都是「把二进制当文本处理」:
- FTP 的 ASCII 模式——Windows 侧把每个
0A展开成0D 0A,Unix 侧反向折叠 - Git 的 autocrlf 处理了本该按二进制对待的文件,通常是
.gitattributes没标 binary - 脚本用文本模式打开文件(没带
b标志)读写
对文本无害,对 exe、zip、png、字体是致命的。
hex 里的三个特征:
- 文件比原始大小大一点点,多出的字节数正好等于原文件里
0A的个数 0D 0A出现得异常密集,且出现在图像数据、压缩数据这类不该有换行的区域- 魔数仍然正确——所以特别容易被误判成别的问题
对策是用二进制模式重传。 已被改写的文件无法可靠还原:原文件里本来就有的 0D 0A 和转换出来的混在一起,分不清哪些该折回去。
形态四:通篇乱码——多半没坏,是加密或压缩
一片看不出规律的字节,第一反应往往是「彻底坏了」。恰恰相反。
| 损坏的文件 | 加密 / 压缩的数据 | |
|---|---|---|
| 局部结构 | 还能看到可读字符串、成片的 00 | 看不到任何重复模式 |
| 字节分布 | 不均匀 | 接近均匀,高熵 |
连续 00 | 常见 | 几乎没有 |
| 头部 | 可能已经被破坏 | 通常有容器魔数 |
高熵本身就是「数据完好」的证据——加密和压缩的目标就是把冗余榨干,结果必然是均匀分布。真正损坏的文件反而会露出结构的残骸。
所以看到通篇乱码,回头看头部:有 GZIP 的 1F 8B、有 ZIP 的 50 4B 03 04、有加密容器自己的固定头,就说明文件是好的,你缺的是密码或对应的工具。
加密 ZIP 和损坏 ZIP 的一句话判据:标准 ZIP 加密只加密内容不加密文件名,所以能在 hex 里直接看到文件名就说明结构还在,问题在密码上;连 EOCD 都找不到,才是真的缺数据。
附:BOM 挡在魔数前面
EF BB BF 是 UTF-8 的 BOM。它出现在文件开头时,会把真正的内容整体往后挤 3 个字节。
后果是解析器读到的第一个字符不是预期的 { 或 <,于是报「格式不对」「意外的字符」——而你用编辑器打开看,一切正常,因为编辑器把 BOM 藏起来了。
只有 hex 视图能看见它。 这也是 JSON 解析、XML 解析、shell 脚本 shebang 失效这几类问题的经典成因。
按症状定位
| 症状 | hex 特征 | 结论 | 怎么办 |
|---|---|---|---|
| 体积远小于预期 | 头部是 <!DOC / {" | 下到了错误页 | 检查链接和登录态 |
| 头对尾不对 | 尾部标记缺失 | 传输截断 | 重新下载 |
| 体积略大 | 数据区 0D 0A 密集 | 文本模式污染 | 二进制模式重传 |
| 通篇乱码 | 高熵、头部有魔数 | 没坏,加密或压缩 | 找密码 / 换工具 |
| 解析报意外字符 | 开头 EF BB BF | BOM 干扰 | 去掉 BOM 另存 |
相关
总结
- 先看文件大小,差一个数量级基本就是下到了错误页,比看 hex 还快
- 头部只回答「是什么」,尾部才回答「全不全」,ZIP 的 EOCD、PNG 的 IEND 都在末尾
- 截断本地修不了,缺的字节就是没有了,唯一出路是重新获取
- 魔数正确不等于文件没问题,文本模式污染改的是中间的换行字节
- CRLF 污染不可逆,因为分不清哪些
0D 0A是原有的,必须二进制重传 - 通篇高熵说明数据完好,那是加密或压缩的正常样子,不是损坏
EF BB BF开头的 BOM 只有 hex 能看见,是一大类「格式不对」报错的真凶