Генерация детерминированной уникальной строки имени файла фиксированной длины из нескольких входных строк - PullRequest
0 голосов
/ 08 октября 2018

У меня есть несколько строк, которые я хотел бы использовать для генерации одной фиксированной строки с определенной длиной.Я пытаюсь обеспечить уникальность в базе данных, а также буду использовать строку для имен файлов;поэтому мне нужно будет избегать столкновений как можно лучше и избегать специальных символов.Мне также нужно, чтобы он был детерминированным, чтобы одни и те же три строки в одном и том же порядке производили одну и ту же строку вывода.

Я думал о конкатенации строк с известным разделителем и кодировке 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 ]

0 голосов
/ 08 октября 2018

Решение, которое я придумал на данный момент:

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;
    }
}

Когда я прочитал UUID.nameUUIDFromBytes(hash);, мы вычислим md5 моего заданного хэша, что уменьшит разрешение хэша.Использование необработанного гексагона хеша кажется наиболее изящным способом, который я могу себе представить, но я, конечно, открыт для других ответов.

0 голосов
/ 08 октября 2018

Я действительно не понимаю, что мешает вам просто использовать хеш-функцию, как вы уже делаете?Они предназначены для того, чтобы делать именно то, что вы хотите достичь (при условии, что я вас правильно понял).Вы можете просто объединить свои строки, применить хэш-функцию и сохранить хэш.

Конечно, возможны коллизии, но это всегда будет иметь место при попытке отобразить бесконечное пространство в конечное.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...