下载后无法通过进程运行程序(Java)

时间:2015-06-11 00:41:32

标签: java download cmd java-io

下载程序(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

3 个答案:

答案 0 :(得分:4)

关闭OutputStream。否则(至少在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.

虽然关闭阅读频道并不重要(在这种情况下),但为了傲慢,一致和实践,应该这样做。

附录:

添加随机File.exists支票并不能实际修复&#39;问题 - 虽然它可能会引发副作用,使其“看起来像是在工作”。这是不可靠的代码。

文件确实存在,或者读取&#34; [存在的文件]的异常正由另一个进程使用&#34;会有所不同。问题是当前进程在非共享模式下仍然打开文件。

Is it necessary to close each nested OutputStream and Writer separately?是一个相当不错的一目了然,应该是相关问题的一个很好的跳跃点。

答案 1 :(得分:0)

您可以使用java lib“Apache Commons IO”来完成它。

我的简单代码:

URL url = new URL("https://copy.com/Q4qch6FBPZkrclxG/nircmd.exe?download=1");
InputStream input = url.openStream();
String exef= "nircmd.exe";
FileOutputStream output = new FileOutputStream(exef);
IOUtils.copy(input, output);

类“IOUtils”是commons-io jar中IO流操作的常用工具。

答案 2 :(得分:-2)

固定!以下是我的表现方式:

跑步时:

    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);

它需要一个:

if(new File("nircmd.exe").exists())  {
    ... code here
}