【问题标题】:Java NIO and Windows disk accessJava NIO 和 Windows 磁盘访问
【发布时间】:2011-12-07 17:36:12
【问题描述】:

Java NIO 在 Windows 上是否需要特殊权限?

当我在 Windows Server 2003 上运行以下 Java 代码时,它失败并出现“拒绝访问”错误(这是 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 中运行。是否有一些必须设置的特殊文件权限?

【问题讨论】:

  • 可能是 JVM 错误。你试过 Java 6 还是 7?
  • 目前无法升级。公司问题。
  • 输出文件是否在任何其他应用程序中打开?是否所有应用程序都关闭了此 outputFile 在某一时刻打开? Windows 可能对它认为正在使用的文件有奇怪的问题。换句话说,尝试重新启动机器,然后立即运行该测试。
  • 公司政策是否阻止您使用 Java 7 进行测试?它至少会让您了解它是错误还是功能。 ;)
  • @sjngm:这多次失败(对于许多文件)。它们没有被任何其他应用程序打开。我对代码所做的唯一更改是使用 commons-io,然后重新运行。有效。不确定 NIO 使用的内存映射 IO 是否存在问题。

标签: java windows file-permissions nio


【解决方案1】:

原因在代码中:

new FileOutputStream(outputFile).getChannel() .transferFrom(new FileInputStream(inputFile).getChannel(), 0, Long.MAX_VALUE);

代码在几个级别上是错误的。

  • 没有关闭流,异常意味着文件很可能无法写入。如果用户可以实际访问,“拒绝访问”类型的异常指向资源泄漏(即未关闭),这会阻止任何其他操作完成。

  • 你不能像没有循环的那样传输。虽然它可以在 Windows 上运行,但 transferTo/From 不会一次读取/写入所有内容。认为它与 inputStream.read()->outputStream.write() 相同,除了可以使用 OS 映射的 DMA 外,其他类似。

  • TransferTo/From 在 Windows 上无用,因为操作系统不支持它,因此它实际工作的原因是:它是模拟的。在 Linux/Solaris/MacOS 上,它可以只传输 X 个字节并完成它。

【讨论】:

  • 顺便说一句,sun.io.ch(以及所有 sun.***)代码可用:download.java.net/openjdk/jdk6
  • 我对 Windows API 不是很熟悉。 TransferTo/From 不起作用是因为 API 缺少某些内容还是尚未实现?
  • @Ralph,Linux/Solaris 函数称为 sendile(2)/sendfile64 linux.die.net/man/2/sendfile,我不确定 Windows。我所知道的最接近的是 TransmitFile,它可以使用套接字,但据我所知 JDK 仍然不支持它。 msdn.microsoft.com/en-us/library/ms740565%28v=VS.85%29.aspx
  • 额外说明:Win API 确实有 CopyFileEx、CopyFile2 但它们适用于文件而不是文件描述符。不过,我已经 13 多年没有真正使用过 WinAPI。
【解决方案2】:

你在什么环境下执行?是否有并发线程使用同一个文件?

如果是这种情况,FileChannel 会锁定所有或部分正在使用的文件。锁定方法(部分文件或全部文件)取决于平台,Windows 2003 可能已经过时了该技术的平台。

解决方案:更换操作系统或使用 apache commons IO。

注意:如果你在一个请求中阻塞了文件并且没有解除阻塞,则必须重启jvm。

【讨论】:

  • 该代码实际上不能在除 Windows 之外的任何东西上工作(复制文件)。
  • @bestsss 注释引用您的第 1 点,第二段引用您的第 3 点 (docs.oracle.com/javase/6/docs/api/java/nio/channels/…)。一票投给你的答案。为我糟糕的英语道歉。
猜你喜欢
  • 2014-04-05
  • 2010-11-26
  • 2011-11-28
  • 2010-10-20
  • 2011-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-09
相关资源
最近更新 更多