java.nio.file.Files.isWriteable не согласуется с java.io.File.canWrite()

У меня есть код Java, делающий следующее:

  1. Создать временный пустой файл с расширением ZIP, используя File.createTempFile()
  2. Удалить это с File.delete() (мы действительно хотели, чтобы он генерировал имя временного файла)
  3. Скопируйте "шаблон" ZIP-файл по тому же пути с com.google.commons.io.ByteStreams.copy() используя новый OutputSupplier дано то же имя файла
  4. Изменить ZIP-архив (удалить каталог) с помощью TrueZIP 7.4.3

В конкретной системе шаг 4 завершается неудачно в соответствии с FsReadOnlyArchiveFileSystemException - "This is a read-only archive file system!" (см. http://java.net/projects/truezip/lists/users/archive/2011-05/message/9)

Отлаживая код TrueZIP, я заметил следующее:

  • Нет никакого дескриптора открытого файла в этом файле между любыми из шагов выше, и определенно не перед шагом 4
  • Проверка того же файла с помощью File.canWrite(), а не NIO возвращает в тот же момент времени (с использованием отладчика), показывает, что он доступен для записи

Вот что вы видите в списке выражений отладчика:

fn => "C:/myworkdir/temp/myfile4088293380313057223tmp.zip"
java.nio.file.Files.isWritable(java.nio.file.Paths.get(fn)) => false
new java.io.File(fn).canWrite() => true

Использование JDK 1.7.04

Есть идеи?

3 ответа

В java.nio.file.Files.isWritable есть ошибка в Windows: она не учитывает неявные разрешения. ошибка Java #7190897

Я бы избегал использования обоих API и вместо этого полагался на исключения, выдаваемые, например, new FileOutputStream(), По крайней мере, они реальны и вызывают серьезную озабоченность. Использование API, о которых вы упоминаете, совершенно бессмысленно, оно вводит временные окна и повторяющийся код. Вы должны поймать IOException в любом случае: зачем писать весь этот код дважды?

Конечный результат не слишком удивителен:

java.nio.file.Files.isWritable(java.nio.file.Paths.get(fn)) => false
new java.io.File(fn).canWrite() => true

File.canWrite вообще не обращает внимания на ACL, а только проверяет атрибут MS-DOS только для чтения.

Files.isWriteable обращает внимание на ACL, но по какой-либо причине (чтобы сломанные программы были сломаны?) Они оставили File.canWrite без исправлений. Это оказывается удачным, потому что в некоторых ситуациях кажется, что он может вернуть false, даже если вы можете открыть файл без проблем.

На самом деле, я бы суммировал такие методы:

  • File.canWrite иногда возвращает true, если вы не можете записать файл.
  • Files.isWriteable иногда возвращает false, когда вы действительно можете записать в файл.

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

Другие вопросы по тегам