下载程序(NirCmd)后如下:
URL website = new URL(
"https://copy.com/Q4qch6FBPZkrclxG/nircmd.exe?download=1");
ReadableByteChannel rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream("nircmd.exe");
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
然后像这样运行它:
Process process = Runtime.getRuntime().exec("nircmd.exe speak text Hi");
但是它抛出了这个异常:
java.io.IOException: Cannot run program "nircmd.exe": CreateProcess error=32, The process cannot access the file because it is being used by another process
at java.lang.ProcessBuilder.start(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at Main.main(Main.java:18)
Caused by: java.io.IOException: CreateProcess error=32, The process cannot access the file because it is being used by another process
at java.lang.ProcessImpl.create(Native Method)
at java.lang.ProcessImpl.<init>(Unknown Source)
at java.lang.ProcessImpl.start(Unknown Source)
... 5 more
最佳答案
关闭输出流。否则(至少在 Windows 中)它会在一段不确定的持续时间内对底层文件资源保持独占写入锁定。
流应该通过调用close
来处理以确定性的方式来避免这个问题。
如果close
没有被调用,那么流将“在未来某个不确定的时间关闭,当/如果终结器运行或程序退出”。正如所见,这种不确定性行为可能会导致错误和不稳定的行为。
为了让生活更轻松,因为正确包装和调用 close
方法非常乏味, try-with-resources可以使用语句:
try (
ReadableByteChannel rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream("nircmd.exe"))
) {
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
}
// Now nircmd.exe can be opened because fos.close()
// is GUARANTEED to have been called (by try-with-resources)
// and the underlying file is no longer [exclusively] opened.
虽然关闭读取 channel 并不那么重要(在本例中),但出于傲慢、一致性和实践的考虑,应该这样做。
附录:
添加随机 File.exists
检查实际上并不能“解决”问题 - 尽管它可能会触发副作用,使其“看起来可以工作”,但它是不可靠的代码.
文件确实存在,或者显示“[确实存在的文件]正在被另一个进程使用”的异常会有所不同。问题是当前进程仍然以非共享模式打开该文件。
Is it necessary to close each nested OutputStream and Writer separately?是一本相当不错的一目了然的书,应该是解决相关问题的一个很好的起点。
关于java - 下载程序后无法通过进程运行程序(Java),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30769710/