#java #windows #file-permissions #nio
#java #Windows #файл-разрешения #nio
Вопрос:
Нужны ли Java NIO специальные разрешения в Windows?
Когда я запускаю следующий код Java на Windows Server 2003, он завершается ошибкой «отказано в доступе» (это все сообщение в окне терминала cygwin):
new FileOutputStream(outputFile).getChannel()
.transferFrom(new FileInputStream(inputFile).getChannel(), 0, Long.MAX_VALUE);
но если я использую Apache commons-io (который, я полагаю, НЕ использует NIO, он работает с теми же входными и выходными файлами:
final FileInputStream inputStream = new FileInputStream(inputFile)
final FileOutputStream outputStream = new FileOutputStream(outputStream)
IOUtils.copy(inputStream, outputStream);
Я работаю на Java 5 с учетной записью администратора. Существует ли какое-либо специальное разрешение на доступ к файлам, которое необходимо установить?
Комментарии:
1. Это может быть ошибка JVM. Вы пробовали Java 6 или 7?
2. На данный момент не удается выполнить обновление. Корпоративная проблема.
3. Открыт ли выходной файл в каком-либо другом приложении? Закрыты ли все приложения, у которых этот выходной файл был открыт в какой-то момент? У Windows могут быть странные проблемы с файлами, которые, по его мнению, используются. Другими словами, попробуйте перезагрузить компьютер, а затем сразу же запустите этот тест.
4. Корпоративная политика не позволяет вам протестировать это с помощью Java 7? Это, по крайней мере, даст вам некоторое представление о том, является ли это ошибкой или особенностью. 😉
5. @sjngm: это не удалось несколько раз (для многих файлов). Они не были открыты ни одним другим приложением. Единственное изменение, которое я внес в свой код, заключалось в использовании commons-io и повторном запуске. Это сработало. Не уверен, что проблема заключалась в IO с отображением памяти, который использует NIO.
Ответ №1:
Причины кроются в коде:
new FileOutputStream(outputFile).getChannel()
.transferFrom(new FileInputStream(inputFile).getChannel(), 0, Long.MAX_VALUE);
Код неверен на нескольких уровнях.
-
нет закрытия потоков, исключение означает, что, скорее всего, файл недоступен для записи. При условии, что пользователь действительно может получить доступ, тип исключения типа «отказано в доступе» указывает на утечки ресурсов (т. Е. Не закрывается), что предотвращает завершение любой другой операции.
-
Вы не можете передавать таким образом без цикла вывода. Хотя он будет работать в Windows, transferTo / From не читает / записывает все сразу. Считайте, что это то же самое, что и InputStream.read()-> OutputStream.write() , это похоже, за исключением того, что он может использовать DMA, отображаемый ОС.
-
transferTo / From бесполезен в Windows, поскольку ОС его не поддерживает, поэтому причина, по которой он действительно работает: он эмулируется. В Linux / Solaris / macOS он может просто передать X байтов и сделать это.
Комментарии:
1. кстати, sun.io.ch (и все вс.***) код доступен: download.java.net/openjdk/jdk6
2. Я не очень хорошо знаком с Windows API. Передача / из не работает, потому что в API чего-то не хватает или он просто еще не реализован?
3. @Ralph, функция Linux / Solaris вызывается sendile(2)/sendfile64 linux.die.net/man/2/sendfile и я не уверен насчет Windows. Самый близкий, о котором я знаю, это TransmitFile, который работает с сокетами, но, насколько мне известно, JDK его не поддерживает. msdn.microsoft.com/en-us/library/ms740565(v=VS.85).aspx
4. дополнительное примечание: Win API имеет CopyFileEx, CopyFile2, но они работают с файлами, а не с файловыми дескрипторами. Тем не менее, я не использовал WinAPI по-настоящему более 13 лет.
Ответ №2:
В каком контексте вы выполняете? Существует ли параллельный поток, использующий один и тот же файл?
Если это ваш случай, FileChannel заблокирует весь или часть используемого файла. Метод блокировки (частичный файл или весь файл) зависит от plataform, и возможно, что windows 2003 была устаревшей plataform для этой техники.
Решение: смените ОС или используйте apache commons IO.
Примечание: Если вы заблокируете файл в одном запросе и не разблокируете, необходимо перезапустить jvm.
Комментарии:
1. Код практически не будет работать (для копирования файлов) ни на чем, кроме Windows.
2. @bestsss Ссылка в примечании на ваш пункт 1rs, а во втором абзаце ссылка на ваш 3-й пункт ( docs.oracle.com/javase/6/docs/api/java/nio/channels /… ). Один голос за ваш ответ. Прошу прощения за мой плохой английский.