java.nio.file.Files.isWriteable не согласуется с java.io.File.canWrite()
У меня есть код Java, делающий следующее:
- Создать временный пустой файл с расширением ZIP, используя
File.createTempFile()
- Удалить это с
File.delete()
(мы действительно хотели, чтобы он генерировал имя временного файла) - Скопируйте "шаблон" ZIP-файл по тому же пути с
com.google.commons.io.ByteStreams.copy()
используя новыйOutputSupplier
дано то же имя файла - Изменить 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, когда вы действительно можете записать в файл.
Я не уверен, какой смысл любого метода сейчас. Поскольку каждый, кто их использует, в конечном итоге должен написать неразрушенный эквивалент, который фактически пытается открыть файл, возникает вопрос, почему они не просто открыли файл, чтобы выполнить проверку самостоятельно.