当前位置: 首页 > 知识库问答 >
问题:

从多个输入字符串生成确定性的唯一固定长度文件名字符串

虞安康
2023-03-14

我有多个字符串,我想用它们来生成一个固定长度的确定性字符串。我试图确保数据库中的唯一性,并且还将使用字符串作为文件名;所以我需要尽可能避免碰撞,并且需要避免特殊字符。我还需要它是确定性的,以便以相同的顺序相同的三个字符串将产生相同的输出字符串。

我想过将字符串串联在已知的分隔符上,并进行base64编码。但是,这不是固定的长度。

我想过连接字符串,从该字符串中获取哈希值,然后对它进行base64编码。但是,默认情况下,base64具有windoze会抱怨的特殊字符,这似乎是不好的做法。

现在我在做这个,感觉也很丑:

protected UUID parseUUID() {
    try {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        List<String> strings = new ArrayList<>();
        strings.add(stringOne);
        strings.add(stringTwo);
        strings.add(stringThree);

        strings.removeIf(str -> str == null || str.isEmpty());
        for(int i = 0; i < strings.size(); i++) {
            String string = strings.get(i);
            string = string.replace("|", "\\|");
            strings.set(i, string);
        }
        String input = String.join("|", strings);
        byte[] hash = digest.digest(input.getBytes());

        return UUID.nameUUIDFromBytes(hash);
    } catch(NoSuchAlgorithmException e) {
        return null;
    }
}

与此方法冲突的概率是多少?从多个输入字符串中生成适合文件名的确定性固定长度字符串的最佳方法是什么?当然不是这样。

共有2个答案

谷梁驰
2023-03-14

我现在想出的解决方案是:

protected String parseHash() {
    try {
        MessageDigest digest = MessageDigest.getInstance("SHA-512");
        List<String> strings = new ArrayList<>();
        strings.add("one");
        strings.add("two");
        strings.add("three");

        strings.removeIf(str -> str == null || str.isEmpty());
        for(int i = 0; i < strings.size(); i++) {
            String string = strings.get(i);
            string = string.replace("|", "\\|");
            strings.set(i, string);
        }
        String input = String.join("|", strings);
        byte[] hash = digest.digest(input.getBytes());
        return DatatypeConverter.printHexBinary(hash);
    } catch(NoSuchAlgorithmException e) {
        return null;
    }
}

如我所读< code > uuid . namuuidfrombytes(hash);将计算我的给定散列的md5,这降低了散列的分辨率。使用哈希的原始十六进制似乎是我能想到的最优雅的方式,但我当然愿意接受其他答案。

荆修明
2023-03-14

我真的不明白,是什么阻碍了你像你已经做的那样使用哈希函数?它们被设计成完全符合你想要实现的目标(前提是我让你正确)。您可以简单地连接字符串,应用哈希函数并存储哈希。

碰撞当然是可能的,但当试图将无限空间映射到有限空间时,情况总是如此。

 类似资料:
  • 我想生成一个固定长度的散列字符串。我正在为此使用MessageDigest API。我注意到API中的这个函数,但它返回的是整数而不是字节数组。 当我尝试使用此重载摘要方法时,我得到 java.security.DigestException:对于 SHA-256 摘要,长度必须至少为 32,或者输出缓冲区对于指定的偏移量和长度来说太小。 有人能举个例子来说明如何生成固定长度的哈希值吗?

  • 我需要生成一个固定长度的文本行: 我现在有的是: 这非常有用,因为生成了一个55个字符的固定长度的字符串。 例如,当可选值为空字符串时,就会出现问题,例如: 在string.format中有空字符串不会给出固定的长度,我仍然需要有30个字符的长度。 任何线索都非常感谢!! 谢谢

  • 我需要产生固定长度的字符串来生成一个基于字符位置的文件。缺少的字符必须用空格字符填充。 例如,字段CITY具有15个字符的固定长度。对于输入“芝加哥”和“里约热内卢”,输出为

  • 问题内容: 我需要产生固定长度的字符串以生成基于字符位置的文件。缺少的字符必须用空格字符填充。 例如,字段CITY具有15个字符的固定长度。对于输入“芝加哥”和“里约热内卢”,输出为 。 问题答案: 从Java 1.5开始,我们可以使用方法java.lang.String.format(String,Object …) 并使用类似于printf的格式。 格式字符串可以完成这项工作。其中表示参数索引

  • 问题内容: 在Go语言中,我只需要一个随机的字符串(大写或小写),没有数字。最快和最简单的方法是什么? 问题答案: Paul的解决方案提供了一个 简单的 通用解决方案。 问题要求 “最快,最简单的方法” 。让我们也讨论 最快的 部分。我们将以迭代的方式得出最终的最快的代码。对每个迭代进行基准测试可以在答案的结尾处找到。 所有解决方案和基准代码都可以在GoPlayground上找到。Playgrou

  • 在Go中,我只想要一个随机的字符串(大写或小写),没有数字。最快和最简单的方法是什么?