Я работаю над процессом Java, который должен эффективно (и рекурсивно) копировать файлы/каталоги из исходного местоположения в целевое.
Для этого я хочу:
- создать замок
- если целевой файл не существует, скопируйте его
- иначе, если конечный файл отличается, скопируйте его
- иначе они одинаковые, так что ничего не делайте
- открыть замок
Чтобы проверить соответствие содержимого, я планировал использовать Apache Commons IO FileUtils
метод contentsEqual(...)
. Для копирования я планировал использовать Apache Commons IO FileUtils
метод copyFile(...)
.
Итак, код, который я придумал (это только для файлов, каталоги обрабатываются рекурсивно до этого метода для файлов):
private static void checkAndUpdateFile(File src, File dest) throws IOException {
FileOutputStream out = new FileOutputStream(dest);
FileChannel channel = out.getChannel();
FileLock lock = channel.lock();
if (!dest.exists()) {
FileUtils.copyFile(src, out);
} else if (!FileUtils.contentEquals(src, dest)) {
FileUtils.copyFile(src, out);
}
lock.release();
channel.close();
out.close();
}
Это блокирует файлы (отлично) и копирует файлы (супер).
Однако всякий раз, когда он копирует файлы, он устанавливает отметку времени последнего изменения скопированных файлов на время копирования. Это означает, что последующие вызовы FileUtils.contentEquals(src, dest)
продолжает возвращать false
, поэтому файлы копируются повторно.
То, что мне действительно нужно, похоже на FileUtils.copyFile(src, dest, true)
, который сохраняет временные метки файла и становится истинным при вызове FileUtils.contentEquals(src, dest)
. Для этого потребуется, чтобы блокировка была на File
, а не на FileOutputStream
, иначе вызов FileUtils.copyFile(src, dest, true)
завершится ошибкой и выдаст исключение, поскольку файл заблокирован.
В качестве альтернативы я решил сделать то, что делает метод FileUtils.copyFile(src, dest, true)
, то есть вызвать dest.setLastModified(src.lastModified())
. Однако это должно быть вызвано после снятия блокировки, что может вызвать проблемы, если один и тот же процесс выполняется более одного раза одновременно.
Я также рассматривал варианты блокировки исходного файла, но это не помогает, так как мне пришлось бы поместить его в FileInputStream
, а я хочу передать File
в FileUtils.copyFile(src, dest)
.
So:
- Есть ли более простой способ добиться того, что я пытаюсь сделать?
- Можно ли поставить блокировку на файл, а не на производную от файла?
- What would be the best way of resolving this?
- i.e. do I just need to write my own approach method for part of this? (probably
copyFile(...)
)
- i.e. do I just need to write my own approach method for part of this? (probably