1. 文件头识别到底解决什么问题:从十六进制看穿 JPEG/PNG/PDF 的真实身份
你有没有遇到过这种情况:下载了一张图片,双击打开却提示「文件已损坏」;或者收到一个后缀是.png的文件,用图片查看器打不开,改成.zip反而能解压。这类问题的根源,往往就藏在文件最前面的几个字节里——也就是我们常说的文件头,或者叫Magic Number(魔数)。
文件头是文件格式在二进制层面的「身份证」。操作系统和应用程序判断一个文件是什么类型,第一眼看的就是这几个字节,而不是你给它起的后缀名。后缀名可以随便改,但文件头是文件生成时写死的。所以,当你需要判断一个文件的真实类型、排查文件损坏、做安全扫描、或者写批量处理脚本时,从十六进制视角读文件头是最直接的手段。
这篇文章聚焦一个很具体的场景:用十六进制识别 JPEG、PNG、PDF 这三种最常见文件的头部特征。我会先拆解它们的字节结构,然后给出可复制的十六进制查看命令和批量校验配置,最后用 TaoToken 的模型对话能力做一个辅助验证的落地动作。适合做文件处理、爬虫、安全排查、以及日常被「假后缀」坑过的开发者。
先说结论,三种格式的文件头特征如下:
| 格式 | 文件头(十六进制) | 对应 ASCII | 典型长度 |
|---|---|---|---|
| JPEG | FF D8 FF | 无(非打印字符) | 3 字节 |
| PNG | 89 50 4E 47 0D 0A 1A 0A | .PNG.... | 8 字节 |
25 50 44 46 2D | %PDF- | 5 字节 |
这里有个细节值得注意:PNG 的文件头是 8 个字节,比 JPEG 和 PDF 都长,而且第 1 个字节0x89是高位字节,这是 PNG 设计者故意选的——用来检测传输过程中是否被错误地当作文本处理(因为很多文本协议会过滤掉高位字节)。PDF 的%PDF-是纯 ASCII,肉眼可读,这也是为什么用文本编辑器打开 PDF 能看到开头那行%PDF-1.7之类的内容。
理解这些特征之后,你就能写出一个不依赖文件后缀、只看字节的判断逻辑。下面我从环境准备开始,一步步带你把这套方法跑通。
2. 前置准备:用 TaoToken 搭建文件头分析的辅助环境
在动手写校验脚本之前,我想先说明一下为什么这里会用到 TaoToken。文件头识别本身是纯本地的字节操作,不需要联网。但在实际工作中,你经常会遇到一些边界情况:比如某个文件头不在你熟悉的列表里,或者你需要快速生成一段解析代码、解释某个字节序列的含义。这时候有一个能理解二进制和文件格式的模型接口,会省很多查资料的时间。
TaoToken 是一个模型调用平台,提供统一的 API 入口,支持对话、编码等场景。它的 API 地址是https://taotoken.net/api,官网是https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=。你可以把它理解成一个「模型网关」——你不需要分别去对接多家模型,而是用一套 Key 和 Base URL 就能调用。
对于这篇文章的场景,我建议你准备两样东西:
第一,一个能查看十六进制的本地工具。Linux/macOS 自带xxd和hexdump,Windows 可以用 PowerShell 的Format-Hex,或者装一个certutil(系统自带)。如果你习惯图形界面,WinHex、HxD 都可以,但命令行更适合批量处理。
第二,一个 TaoToken 的 API Key。获取路径是:登录官网后进入控制台,在 API Keys 页面创建一个 Key。控制台地址是https://taotoken.net/console,API Keys 页面是https://taotoken.net/api-keys。创建时注意保存好,Key 只显示一次。
拿到 Key 之后,你需要确认三件套:Base URL、Key、Model ID。Base URL 用https://taotoken.net/api,Key 就是你刚创建的那串字符,Model ID 根据你需要的场景选——如果只是做文件格式问答,用对话类模型即可;如果要生成解析代码,可以用编码能力更强的模型。具体可用的 Model ID 可以在模型对话页面查看:https://taotoken.net/models。
这里要提醒一句:TaoToken 是模型调用平台,不是文件编辑器,也不做文件存储。你的文件始终在本地,字节读取也在本地完成,TaoToken 只在你需要「问模型」的时候参与。这个边界要分清楚,避免把敏感文件内容直接发给模型。
环境准备好之后,我们进入核心部分:可复制的十六进制查看与批量校验配置。
3. 可复制配置:十六进制查看命令与批量校验脚本
这一节是全文的技术核心,我会给出完整的命令和配置片段,你可以直接复制到终端或脚本里运行。
3.1 单文件十六进制查看
先看最基础的:怎么读一个文件的前几个字节。
Linux/macOS 下用xxd:
# 读取前 16 个字节,-l 指定长度 xxd -l 16 test.jpg输出大概是这样:
00000000: ffd8 ffe0 0010 4a46 4946 0001 0100 0001 ......JFIF......左边是偏移地址,中间是十六进制,右边是对应的 ASCII 可打印字符。你可以看到 JPEG 的开头就是ffd8 ffe0,前三个字节ff d8 ff正是 JPEG 的标志。
用hexdump也可以:
hexdump -C -n 16 test.png-C表示规范格式,-n 16表示只读 16 字节。
Windows PowerShell 下:
Format-Hex -Path .\test.pdf -Count 16或者用系统自带的 certutil:
certutil -dump test.pdfcertutil 会输出一大段信息,但开头部分就能看到文件头。
3.2 批量校验脚本
单个文件看头信息很简单,但实际场景往往是几百上千个文件。下面给一个 Python 脚本,批量扫描目录,根据文件头判断真实类型,并和扩展名做对比。
import os import sys # 文件头特征表,key 是十六进制前缀,value 是类型名 MAGIC_NUMBERS = { bytes.fromhex("FFD8FF"): "JPEG", bytes.fromhex("89504E470D0A1A0A"): "PNG", bytes.fromhex("255044462D"): "PDF", bytes.fromhex("47494638"): "GIF", bytes.fromhex("504B0304"): "ZIP", bytes.fromhex("52617221"): "RAR", } def detect_type(filepath): with open(filepath, "rb") as f: header = f.read(8) for magic, name in MAGIC_NUMBERS.items(): if header.startswith(magic): return name return "UNKNOWN" def scan_dir(root): for dirpath, _, filenames in os.walk(root): for fn in filenames: fp = os.path.join(dirpath, fn) real = detect_type(fp) ext = os.path.splitext(fn)[1].lower().lstrip(".") # 扩展名归一化 ext_map = {"jpg": "JPEG", "jpeg": "JPEG", "png": "PNG", "pdf": "PDF", "gif": "GIF", "zip": "ZIP", "rar": "RAR"} expect = ext_map.get(ext, "UNKNOWN") flag = "OK" if real == expect else "MISMATCH" print(f"[{flag}] {fp} | 实际={real} 期望={expect}") if __name__ == "__main__": scan_dir(sys.argv[1] if len(sys.argv) > 1 else ".")这个脚本的逻辑很直白:读每个文件的前 8 个字节,和特征表比对,然后和扩展名推断的类型做对照。输出里MISMATCH的就是「后缀和真实类型不符」的文件,这类文件要么是被人为改过后缀,要么是下载/传输过程中损坏。
3.3 用 TaoToken 辅助生成解析逻辑
如果你遇到一个不在特征表里的格式,或者想快速扩展这个脚本,可以用 TaoToken 的模型对话来问。请求示例(以 curl 为例):
curl https://taotoken.net/api/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY" \ -d '{ "model": "YOUR_MODEL_ID", "messages": [ {"role": "user", "content": "文件头是 0x1F8B08 的是什么格式?给出 Python 判断代码"} ] }'把YOUR_API_KEY和YOUR_MODEL_ID替换成你自己的。模型会返回格式名称和一段可用的判断代码。这样你就不用每次都去翻文档。
注意:不要把整个文件的二进制内容发给模型,只发文件头那几十个字节就够了。既省 token,也避免敏感数据外泄。
4. 验证请求:跑一遍看结果是否符合预期
配置写好了,接下来要验证它真的能工作。我准备三个测试文件,分别造一个正常的和一个「伪装」的。
4.1 造测试文件
# 正常 JPEG(用系统里任意一张图,或者用 printf 造一个最小头) printf '\xff\xd8\xff\xe0\x00\x10JFIF' > real.jpg # 伪装文件:把 JPEG 的头写进一个 .png 文件 cp real.jpg fake.png # 正常 PDF 头 printf '%%PDF-1.7\n' > real.pdf # 正常 PNG 头 printf '\x89PNG\r\n\x1a\n' > real.png4.2 跑校验脚本
python3 detect.py ./testdir预期输出:
[OK] ./testdir/real.jpg | 实际=JPEG 期望=JPEG [MISMATCH] ./testdir/fake.png | 实际=JPEG 期望=PNG [OK] ./testdir/real.pdf | 实际=PDF 期望=PDF [OK] ./testdir/real.png | 实际=PNG 期望=PNG看到fake.png被标记为MISMATCH,说明脚本正确识别出了「后缀是 png 但真实类型是 JPEG」的情况。这就是文件头识别的价值——它不信任后缀,只看字节。
4.3 用模型对话做二次确认
如果你对某个判断结果不确定,可以把文件头字节贴到 TaoToken 的模型对话页面(https://taotoken.net/models)问一下。比如输入「文件头 FFD8FFE000104A464946 是什么格式,可能是什么相机拍的」,模型会结合 JFIF 标识给出更细的解释。这一步不是必须的,但在排查疑难文件时很有用。
验证通过之后,你就可以把这个脚本挂到你的文件处理流水线里,作为入库前的第一道校验。
5. 常见报错排查:401、local proxy failed、reading choices 怎么处理
这一节整理几个我在实际使用中踩过的坑,尤其是调用 API 时容易遇到的报错。
5.1 401 Unauthorized
这是最常见的错误,原因通常是 Key 不对或没带上。检查三点:
第一,请求头里Authorization: Bearer YOUR_API_KEY格式是否正确,Bearer和 Key 之间有一个空格。第二,Key 是否已经过期或被删除,去https://taotoken.net/api-keys确认。第三,是否把 Key 复制多了空格或换行。我试过因为复制时带了个换行,排查了十分钟。
5.2 local proxy failed
这个报错通常出现在你本地设置了网络代理,但代理没有正常工作时。注意,这里说的是你本机开发环境可能存在的代理配置问题,不是让你去配置什么特殊网络工具。解决办法是检查你的环境变量HTTP_PROXY/HTTPS_PROXY是否指向了一个不可用的地址,临时取消掉再试:
unset HTTP_PROXY HTTPS_PROXY如果你本来就没有设置代理,那这个报错可能是本地网络栈的问题,重启终端或检查 DNS 即可。
5.3 reading choices 相关报错
这类报错一般出现在解析模型返回结果时。模型返回的 JSON 结构里,choices是一个数组,如果你直接按对象取就会报错。正确取法:
import json resp = json.loads(raw) content = resp["choices"][0]["message"]["content"]如果choices为空,说明模型没有返回有效内容,可能是请求被截断或参数有误。检查max_tokens是否设得太小,或者messages是否为空。
5.4 OAuth 相关报错
如果你用的是 Claude Code 之类的工具接入,可能会遇到 OAuth 认证失败。这类工具通常需要你配置 Base URL、Key、Model ID 三件套。以 Claude Code 为例,配置文件里要写清楚:
{ "base_url": "https://taotoken.net/api", "api_key": "YOUR_API_KEY", "model": "YOUR_MODEL_ID" }三件套缺一不可,尤其是 Model ID 写错会直接导致 404 或模型不存在。如果你用的是 Cline 或 CC Switch 这类工具,配置项名称可能不同,但核心就是这三个值。Codex 的auth.json里也是类似结构,把 Base URL 指向https://taotoken.net/api,Key 填进去,Model ID 选对即可。
排查的时候有个通用思路:先用 curl 直接打 API,确认 Key 和网络没问题,再去配置工具。这样能把问题范围缩小到「是 API 问题还是工具配置问题」。
6. 把文件头校验接进你的工作流
文件头识别这件事,单次做没什么感觉,但一旦接进工作流,价值就出来了。我给你几个落地建议。
第一,在文件上传入口加一道校验。用户上传的图片,先读前 8 个字节,确认是 JPEG 或 PNG 再入库,避免有人把可执行文件改成.jpg传上来。
第二,在爬虫下载环节做校验。下载完的图片,用文件头判断真实类型,再决定存成什么后缀,避免一堆「假 png」。
第三,在安全排查时批量扫描。用第 3 节的脚本扫一遍服务器上的可疑目录,MISMATCH的文件重点看。
如果你需要长期跑这类编码任务,或者想把文件校验、格式转换、异常解释串成一个自动化流程,可以考虑用 TaoToken 的 Coding Plan,地址是https://taotoken.net/coding-plan。它适合需要持续调用模型做编码辅助的场景,比单次对话更划算。
最后说一个我自己的习惯:每次遇到不认识的格式,先把前 16 个字节xxd出来,然后去查特征表。查不到就用模型对话问一下,把答案补进自己的MAGIC_NUMBERS字典。日积月累,你手里就有一张越来越全的文件头速查表,比任何工具都好用。文件头不会骗人,后缀会。