Java NIO и доступ к дискам Windows

#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 /… ). Один голос за ваш ответ. Прошу прощения за мой плохой английский.