首页 > 解决方案 > 出于完整性目的对文本文件进行哈希处理

问题描述

我有一个更一般的要求来跟踪提交到源代码中并部署在二进制文件中的资产文件中的更改,但现在我正在单元测试上下文中实现它,并面临未来的潜在问题。在问 TLDR 问题之前,我将展示很多上下文信息。

设想

一些应用程序资产是从通过 [1] 提交到 Git 存储库的 CSV 文件加载的ClasspathResource,它们有时可能会更改。更改发生在提交之间,但对于运行时应用程序,更改发生在应用程序的不同版本之间。

我的测试解决方案

我已经实施了以下机制来提醒我资源的变化:

@Before
public void setUp() throws Exception
{
    assertEquals("Resource file has changed. Make sure the test reflects the changes in the file and update the checksum", MD5_OF_FILE,
                 DigestUtils.md5Hex(new ClassPathResource("META-INF/resources/assets.csv").getInputStream()));
 
}

基本上,我希望我的单元测试失败,直到我明确编码文件的校验和。当我运行时,md5sum assets.txt我将结果硬编码到代码中,以便测试知道它们正在使用文件的固定版本。

问题

我在我自己的 Windows 机器上运行了测试,并且工作得很好。切换到Linux,我发现他们失败了。我立刻意识到这可能是由于我完全忘记了行尾的原因。

在特定情况下,Git 配置为提交文件LF但签出(在 Windows 中)CRLF。此配置对于使用源代码是合理的。

所以我需要检查资产文件是否以智能方式更改,允许框更改/重新解释行尾。对于将存储文件哈希并比较实际资产文件(可能已更改)的运行时应用程序尤其如此,对差异执行纠正措施 ==> 重新加载资产。

TL;博士

给定一个文本文件,我可以提取和存储任何散列(不仅仅是加密,我使用了 MD5),我怎么知道它已经改变,而不管文件处理的环境如何,这可能会修改行尾?

注意 我要求不要在资产本身中使用版本控制系统(例如,第一行有增量版本,因为开发人员将无法正确更新)。

[1] Spring框架工具封装Class.getResourceAsStream

标签: hashline-endings

解决方案


一种解决方案可能是将文件规范化为选择的行结尾,即 alwaysCRLF或 always LF,然后计算该规范化内容的加密哈希。

例如,计算md5sum | dos2unix file并使用适当Stream的代码来动态规范化文件


推荐阅读