大家好,我是 SiKi老师。两位协作者都交了一份同名资源,应该留下哪一份?文件名相同只说明名字相同。要判断手里的内容是否一致,我会先保留两份输入,再比较实际字节;需要给交接记录留一个摘要时,再计算哈希,不直接覆盖其中一份。
本文使用 Windows、Python 3.12.14 和标准库 hashlib。样例全是自拟内存字节,不读取真实游戏资源,没有验证 Unity、Godot 的导入、图像显示或打包结果。封面上的文件卡片是概念插画,不是本文执行输出,也不是实际 PNG 文件的检验记录。
一 用小样例比较内容而不是名字
先准备三份字节,其中前两份相同,第三份只改一个数字:
a=b'level:1\n'b=b'level:1\n'c=b'level:2\n'print(a==b,a==c)本地输出是True False。这里没有文件路径参与判断,比较的就是两份内存数据。如果资源清单只保存文件名,它没有包含足够信息来得出这组比较结果。扩展名、文件大小或修改时间也不能替代对内容的核对。
这三份数据不是图片格式。把变量改名叫texture,或在旁边写上.png,都不会让它成为可导入的图片。因此本文只把它用于解释字节身份,不演示游戏资源加载。真实交接中先保留双方路径和来源,比较期间不要把同名文件覆盖掉。
二 给同一份字节计算摘要
对同一组输入计算 SHA-256 的十六进制摘要:
importhashlibdefdigest(data):returnhashlib.sha256(data).hexdigest()print(digest(a)==digest(b),digest(a)==digest(c))print(len(digest(a)))本地得到True False,摘要字符串长度为64。这是这组输入的实际结果,不是在证明所有不同输入都会产生不同摘要。有限长度摘要可能存在碰撞,不能把“摘要相同”写成数学意义上的“绝对相同”。本例数据已经在内存中,需要直接比较时也可以使用上一节的字节比较。
交接记录若保存摘要,应同时注明算法和输入范围。本例算法是 SHA-256,输入是全部字节,不包括文件名、路径或修改时间。不能拿另一种算法、只读了前半部分的数据,或经过转换后的内容来作同一条记录的比较。
三 分块处理也要覆盖完整输入
hashlib 支持多次更新同一个对象。小样例可以这样核对分块结果:
h=hashlib.sha256()h.update(a[:3])h.update(a[3:])asserth.hexdigest()==digest(a)本地断言通过。两次更新按顺序覆盖了a的全部字节,没有跳过或重复片段。这不是读取大文件的完整实现,也没有测吞吐量、内存峰值或读取期间被其他进程修改的情况。
如果后续改成真实文件流,需要处理文件打开失败、读取中断和输入变化等问题。不能在中途失败后把已读前缀的摘要当成整份资源的摘要,更不能仅因为计算函数正常返回就宣称整个交接包已经验收。
四 换行与编码可能让字节不同
本地另测b'level:1\n'和b'level:1\r\n',它们的字节与摘要都不相同。两段文字看起来可能接近,按字节核对却不是同一份内容。这种差异先记下来,是否允许统一换行由项目协议决定,比较器不应悄悄改写输入。
文字还需要约定编码。自拟文字“关卡”分别编码成 UTF-8 和 UTF-16-LE,实际字节不同,摘要也不同。直接把普通字符串交给hashlib.sha256,本地得到TypeError;示例没有实现自动编码识别,也没有规定哪一种编码适合所有项目。
如果团队真正想比较解析后的语义,应另设明确规则。例如两份配置排版不同但解析结果相同,那是另外一个问题。本文不把文本规范化、图片像素相等、引擎资源等价和原始字节相等混为一谈。
五 记录比较结果后再决定怎么交付
独立测试覆盖相同输入、不同输入、摘要长度、分块与一次性计算相等、空输入、不同换行、不同编码,以及字符串误传失败。测试没有读取磁盘,也没有删除、覆盖或上传资源。
我会在交接记录里分别保留来源位置、算法、比较范围和结论,再由内容负责人决定保留哪份。哈希不是版权证明,不证明来源可信或资源安全,也不能代替实际导入和运行验收。本文没有进行任何安全鉴定或破解操作。
遇到同名冲突时,可以先用自己编写的几字节输入复现比较过程,不需要发送真实资源包。你要核对的是原始字节、解析后的配置值,还是画面效果?先说清这一层,才知道摘要能回答什么、还缺哪一步验证。
依据:Python 3.12 hashlib 官方文档。这里只使用标准库接口及自拟小样例,不引用课程资料或第三方资源。