Обнаружить измененные файлы в каталоге (Java 8) из дайджеста или контрольной суммы - PullRequest
0 голосов
/ 07 ноября 2019

Я ищу простой способ определить, не изменились ли файлы в каталоге между перезагрузками, чтобы избежать ненужной синхронизации. Что было бы самым простым способом сделать это в библиотеках Java 8? Должен ли я XOR дайджест md5 каждого файла или XOR контрольные суммы каждого файла?

ATM, нам не нужно обрабатывать вход в подкаталоги.

Также мы не должны использовать событие ОС для обнаружения этого изменения, поскольку метод обнаружения будет вызываться только при запуске. Количество файлов в каталоге может изменяться между различными версиями приложения, но эти файлы обычно не изменяются между перезагрузками.

Это похоже на соответствующий пост: https://crypto.stackexchange.com/questions/1368/is-it-a-good-idea-to-use-bitwise-xor-on-a-set-of-md5-sums

Ответы [ 3 ]

2 голосов
/ 07 ноября 2019

Это зависит от того, что вы подразумеваете под «простым».

С одной стороны, вы можете использовать временные метки файла. Но проблема в том, что временные метки могут вводить в заблуждение:

  • Проверки в зависимости от отметок времени могут повлиять на проблемы с перекосом часов. (Это зависит от того, какие часы задействованы, и от того, как часы управляются.)

  • Возможно, что временные метки файла будут сброшены (например, пользователем «root»), создавая впечатление, чтофайл не изменился.

  • Изменить «измененную» метку времени файла тривиально без фактического изменения файла;например, touch.

С другой стороны, если вы используете контрольные суммы, у вас есть другие проблемы:

  • Вычисление контрольной суммы файла влечет за собой чтениевесь файл. (Частичной контрольной суммы недостаточно, чтобы обнаружить изменения, в общем.) Некоторые алгоритмы контрольной суммы также относительно дороги.

  • Вам также необходимо знать, что такое предыдущий контрольная сумма для файла была. Это означает, что вам нужен способ / место для его хранения. Это может быть просто другой файл, но тогда вам понадобится некоторая инфраструктура для обновления этого файла (надежно) как часть процедуры синхронизации.

  • XOR при использовании нескольких контрольных сумм возникает проблема, из-за которой вы не можетеНе знаю, какие файлы были изменены. Если один файл изменяется, вам нужно синхронизировать их все.

  • Теоретически возможно изменение файла и контрольная сумма MD5 будет одинаковой: вероятность 1 в 2 ^ 128. Вы, вероятно, можете обесценить это ... если только ваше приложение не критично для безопасности(Обратите внимание, что атаки коллизии MD5 практичны в некоторых контекстах ; см. https://en.wikipedia.org/wiki/Collision_attack)


Другое дело, что я подозреваю, что вы пытаетесь решить решенную проблемуНапример, утилита Linux / Unix rsync имеет возможность использовать временные метки или (MD5) контрольные суммы, чтобы решить, какие файлы необходимо синхронизировать.

Вам не нужно реализовывать все самостоятельно (в Java).

В ответ на ваше «у нас нет доступа к старому дереву файлов» существует простое решение для этого. Каждый раз, когда вы перезагружаетесь:

  1. скопировать дерево файлов
  2. сравнить текущие файлы с копией, которую вы сделали в последний раз , которую вы перезагрузили.

Как я уже говорил в комментарияхваше воображение.

0 голосов
/ 09 ноября 2019

Вот процедура, которую я ищу для генерации хеша из всех файлов в каталоге.

/**
 * Recursively compute a single md5 signature of all files in a directory. Is typically 
 * used to determine if a file in a directory or any of the sub directories have been 
 * modified since the last digest was taken.
 */
public class DirectoryDigest {

    MessageDigest md = null;

    public DirectoryDigest() {
        try {
            md = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            ApplicationManager.logStackTrace(e);
        }
    }

    public void update(Path dirPath) {
        update(dirPath, null);
    }

    public synchronized void update(Path dirPath, String extension) {

        try {
            Files.newDirectoryStream(dirPath).forEach(file -> {
                if (!Files.isDirectory(file) && file.getFileName().toString().endsWith(extension)) {
                    if (extension != null && !file.getFileName().toString().endsWith(extension)) {
                        System.out.println("not processing: " + file.getFileName());
                        return;
                    }
                    try {
                        byte[] bytes = Files.readAllBytes(file);
                        md.update(bytes);
                    } catch (IOException e) {
                        ApplicationManager.logStackTrace(e);
                    }
                } else {
                    update(file, extension);
                }
            });
        } catch (IOException e) {
            ApplicationManager.logStackTrace(e);
        }
    }

    /**
     * Returns md5 digest signature and resets the digest object.
     * @return
     */
    public String digest() {
        return String.format("%032X", new BigInteger(1, md.digest()));
    }
}

Используется так:

DirectoryDigest dd = new DirectoryDigest();
dd.update(csConfigDirPath, ".xml");
String currentPeripheralHash = dd.digest();
0 голосов
/ 07 ноября 2019

Полезно ли время изменения файла в вашей ситуации? Md5sum - точный способ для некоторых ситуаций.

...