Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从批处理文件读取InputStream';s进程跳到下一行_Java_Windows_Process_Batch File_Inputstream - Fatal编程技术网

Java 从批处理文件读取InputStream';s进程跳到下一行

Java 从批处理文件读取InputStream';s进程跳到下一行,java,windows,process,batch-file,inputstream,Java,Windows,Process,Batch File,Inputstream,我正在尝试使用Runtime.exec()运行批处理文件,然后将其InputStream输出到JTextArea。我所拥有的一切起作用,但只是部分。发生的情况是批处理文件运行,但如果它执行的命令不是“echo”之类的命令,则该命令立即终止,并执行下一行。例如,假设我尝试运行一个简单的批处理文件,如下所示: @echo off echo hello. waiting 5 seconds. timeout /t 5 /nobreak > NUL echo finished. goodbye.

我正在尝试使用Runtime.exec()运行批处理文件,然后将其InputStream输出到JTextArea。我所拥有的一切起作用,但只是部分。发生的情况是批处理文件运行,但如果它执行的命令不是“echo”之类的命令,则该命令立即终止,并执行下一行。例如,假设我尝试运行一个简单的批处理文件,如下所示:

@echo off
echo hello. waiting 5 seconds.
timeout /t 5 /nobreak > NUL
echo finished. goodbye.
    String line;
    while (!complete || (line=in.readLine()) != null) {
        gui.setTextAreaText(line + "\n");
    }
批处理文件执行,JTextArea显示

hello. waiting 5 seconds.
finished. goodbye.
但是它在中间不等待5秒。

我不明白它为什么这样做。下面是我用来运行批处理文件并读取其InputStream的内容

private class ScriptRunner implements Runnable {
private final GUI.InfoGUI gui; // the name of my GUI class
private final String script;

public ScriptRunner(final GUI.InfoGUI gui, final File script) {
    this.gui = gui;
    this.script = script.getAbsolutePath();
}

@Override
public void run() {
    try {
        final Process p = Runtime.getRuntime().exec(script);
        StreamReader output = new StreamReader(p.getInputStream(), gui);
        Thread t = new Thread(output);
        t.start();
        int exit = p.waitFor();
        output.setComplete(true);
        while (t.isAlive()) {
            sleep(500);
        }
        System.out.println("Processed finished with exit code " + exit);
    } catch (final Exception e) {
        e.printStackTrace();
    }
}

}
private class StreamReader implements Runnable {
private final InputStream is;
private final GUI.InfoGUI gui;

private boolean complete = false;

public StreamReader(InputStream is, GUI.InfoGUI gui) {
    this.is = is;
    this.gui = gui;
}

@Override
public void run() {
    BufferedReader in = new BufferedReader(new InputStreamReader(is));
    try {
        while (!complete || in.ready()) {
            while (in.ready()) {
                gui.setTextAreaText(in.readLine() + "\n");
            }
            sleep(250);
        }
    } catch (final Exception e) {
        e.printStackTrace();
    } finally {
            try {
                in.close();
        } catch (final Exception e) {
                e.printStackTrace();
    }
}

public void setComplete(final boolean complete) {
    this.complete = complete;
}

}
public void sleep(final long ms) {
try {
    Thread.sleep(ms);
} catch (final InterruptedException ie) {
}
}
我知道我的代码相当混乱,而且我确信它包含语法错误


谢谢你能为我做的一切

ready方法只告诉流是否可以保证可以立即读取某些内容,而不会阻塞。您不能真正信任它,因为总是返回
false
是一个有效的实现。具有缓冲区的流只有在缓冲了某些内容时才会返回
true
。所以我怀疑你的问题在这里:

    while (!complete || in.ready()) {
        while (in.ready()) {
            gui.setTextAreaText(in.readLine() + "\n");
        }
        sleep(250);
    }
应该这样读:

@echo off
echo hello. waiting 5 seconds.
timeout /t 5 /nobreak > NUL
echo finished. goodbye.
    String line;
    while (!complete || (line=in.readLine()) != null) {
        gui.setTextAreaText(line + "\n");
    }

这可能是因为您的“timeout…”命令返回了一个错误

测试它的三种方法:

  • 检查“timeout…”命令是否在Windows命令提示符下工作
  • 将脚本中的“timeout…”替换为“ping-n127.0.0.1>NUL”(它基本上做相同的事情)
  • 从脚本中删除除“timeout/t5/nobreak>NUL”之外的所有内容。如果超时失败,则进程应返回错误(1),因为它是最后执行的命令

  • 问题肯定出在
    timeout.exe
    中。如果在带有
    timeout
    的行之后添加
    echo%errorlevel%
    ,您将看到如果从java运行,它将返回
    1
    。如果以常规方式运行,则为
    0
    。可能,它需要一些特定的控制台功能(即光标定位),当从java进程运行时,这些功能会被抑制

    在从Java运行时,我能做些什么来让它工作吗

    如果您不需要运行任何批处理文件的能力,则考虑用<代码> ping <代码>替换<代码>超时< /代码>。否则。。。我试着用内核32运行批处理文件。CreateProcess和超时运行正常。但是,您还需要通过本机调用实现进程输出的读取


    我希望有人能提出更好的方法。

    您正在创建一个
    进程
    ,但您并不是在读取它的标准错误流。进程可能正在将消息写入其标准错误以告诉您存在问题,但如果您没有读取其标准错误,则无法读取这些消息

    这里有两个选项:

  • 由于您已经有一个类从流(
    StreamReader
    )读取数据,因此将其中的另一个连接到进程的标准错误流(
    p.getErrorStream()
    )并在另一个
    线程中运行它。当调用
    p.waitFor()
    返回时,您还需要在错误StreamReader上调用
    setComplete
    ,并等待运行它的线程死亡

  • Runtime.getRuntime().exec()
    的使用替换为。这个类在Java5中是新的,它提供了一种运行外部进程的替代方法。在我看来,与
    Runtime.getRuntime().exec()
    相比,它最显著的改进是能够将进程的标准错误重定向到其标准输出中,因此您只有一个流可以读取

  • 我强烈建议使用第二个选项,选择将流程的标准错误重定向到其标准输出中

    我把你的密码换了

            final Process p = Runtime.getRuntime().exec(script);
    

    另外,我手头没有您的GUI代码,因此我将流程的输出写到
    System.out

    当我运行您的代码时,我得到了以下输出:

    hello. waiting 5 seconds. ERROR: Input redirection is not supported, exiting the process immediately. finished. goodbye. Processed finished with exit code 0 你好等待5秒。 错误:不支持输入重定向,立即退出进程。 完成了。再见。 已处理完毕,退出代码为0 如果您看到该错误消息,您可能会发现
    timeout
    命令出现了问题


    顺便说一句,我在你的一条评论中注意到,乌赞建议的命令都不起作用。我将
    timeout
    行替换为
    ping-n127.0.0.1>NUL
    ,脚本按预期运行。我无法重现这个问题。

    谢谢你的提示。你是对的;java中的errorlevel为1,但命令提示符中的errorlevel为0。在从Java运行时,我能做些什么来让它工作呢?我尝试的所有不同命令仍然会返回错误1。除了运行“cmd/c file.bat”,我还能做什么?哦!我尝试创建另一个StreamReader来读取进程的错误流,我收到了相同的消息!我只是浏览了一下消息,认为这意味着你永远无法读取批处理文件的错误流,而不是超时。。。我想这更有道理。谢谢你帮忙。然而,我仍然无法找到最终的解决方案。我在批处理文件中主要做的是使用adb shell在连接的Android设备上运行某些命令。。。如果问题出现在命令中,那么我可以做些什么来解决问题?另外,关于ping工作/不工作。。。对不起,那是我的错。我已经处理这个问题好几天了,有一次我将批处理文件更改为timeout和ping,它跳过了超时,但我记错了,认为ping也提前终止了。。。很抱歉。