Блокировка файла при копировании с помощью Commons IO - PullRequest
4 голосов
/ 23 января 2009

Я использую Apache Commons IO:

     FileUtils.copyFileToDirectory(srcFile, destDir)

Как заставить Windows блокировать файл назначения во время копирования? Windows правильно блокирует файл, если я использую:

      Runtime.getRuntime().exec(
      "cmd /c copy /Y \"" + srcFile.getCanonicalPath() + "\" \""
          + destDir.getCanonicalPath() + "\"").waitFor();

Примечания: Конфликт не с локальной программой, а с внешней. Файл копируется в удаленную систему. Удаленная система обрабатывает файл до завершения копирования. Поскольку системы являются Windows, обычное копирование блокирует файл и блокирует доступ внешней программы.

Ответы [ 3 ]

6 голосов
/ 02 февраля 2009

java.nio.channels.FileChannel позволит вам получить FileLock для файла, используя метод, родной для базовой файловой системы, при условии, что такая функциональность поддерживается.

Эта блокировка действует для всех процессов на компьютере, даже не Java. (На самом деле блокировка удерживается от имени конкретного экземпляра JVM, поэтому не подходит для управления конфликтами между несколькими потоками в процессе или несколькими процессами в одной JVM).

Здесь много предостережений, но стоит разобраться, работаете ли вы под Windows.

Из Javadoc:

Этот API-интерфейс блокировки файлов предназначен для непосредственного сопоставления с собственными средствами блокировки базовой операционной системы. Таким образом, блокировки, хранящиеся в файле, должны быть видны всем программам, которые имеют доступ к файлу, независимо от языка, на котором эти программы написаны.

То, блокирует ли блокировка на самом деле доступ другой программы к содержимому заблокированной области, зависит от системы и поэтому не определено. Собственные средства блокировки файлов в некоторых системах просто рекомендательные, это означает, что программы должны совместно соблюдать известный протокол блокировки, чтобы гарантировать целостность данных. В других системах собственные блокировки файлов являются обязательными. Это означает, что если одна программа блокирует область файла, то другим программам фактически запрещается доступ к этой области способом, который нарушил бы блокировку. В других системах независимо от того, являются ли собственные блокировки файлов рекомендательными или обязательными, их можно настраивать отдельно для каждого файла. Для обеспечения согласованного и правильного поведения на разных платформах настоятельно рекомендуется использовать блокировки, предоставляемые этим API, как если бы они были консультативными блокировками.

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

В некоторых системах закрытие канала освобождает все блокировки, удерживаемые виртуальной машиной Java в базовом файле, независимо от того, были ли получены блокировки через этот канал или через другой канал, открытый для того же файла. Настоятельно рекомендуется использовать в программе уникальный канал для получения всех блокировок в любом файле.

Некоторые сетевые файловые системы разрешают использовать блокировку файлов с отображенными в память файлами только тогда, когда заблокированные области выровнены по страницам и кратны размеру страницы базового оборудования. Некоторые сетевые файловые системы не реализуют блокировки файлов в регионах, которые выходят за определенную позицию, часто 230 или 231. В целом, следует соблюдать особую осторожность при блокировке файлов, находящихся в сетевых файловых системах.

4 голосов
/ 23 января 2009

Java изначально не поддерживает блокировку файлов.

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

Было бы полезно получить больше информации о том, зачем вам сначала нужно заблокировать файл.

Разногласия не с местным программный, но внешний. Файл копируется в удаленную систему. Удаленная система обрабатывает файл до завершения копирования. Поскольку системы являются Windows, обычное копирование блокирует файл и блокирует внешняя программа из доступа.

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

1 голос
/ 23 января 2009

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

Еще лучше, вы можете написать в * .tmp. Затем проверьте, существует ли файл назначения. Переименуйте файл dest в * .bak, если он существует. Наконец переименуйте * .tmp -> dest.

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