需要运行sqlcmd来控制到数据库的本地连接。当我试图读取OutputStream以获得sql“提示”时,read()方法根本不会返回。
尝试使用ProcessBuilder和Runtime运行该进程。getRuntime()。exec()也尝试在“cmd /c”下运行。当从命令行运行sqlcmd时,我得到类似“1〉"的提示。预期在OutputStream中看到该提示...
这是我代码-我只是调用以“sqlcmd”开头的
代码示例:
package org.example;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws Exception {
System.out.println(start("sqlcmd"));
System.out.println(send("select * from spt_monitor\ngo\n"));
}
public static Process process = null;
public static String start(String command) throws Exception {
if(process != null && process.isAlive()) {
throw new Exception("another session already exists");
} else {
ProcessBuilder builder = new ProcessBuilder(command);
builder.redirectErrorStream(true);
process = builder.start();
return "";//response();
}
}
public static String send(String command) throws Exception {
if(process == null || !process.isAlive()) {
throw new Exception("no local session exists");
} else {
process.getOutputStream().write(command.getBytes());
process.getOutputStream().flush();
return response();
}
}
private static String response() throws IOException {
StringBuilder sb = new StringBuilder();
char[] array = new char[1024];
System.out.println("reading output...");
try (InputStreamReader isr = new InputStreamReader(process.getInputStream())) {
int len;
do {
len = isr.read(array);
if(len > 0)
sb.append(String.valueOf(array));
} while (len > 0);
}
return sb.toString();
}
}
1条答案
按热度按时间e5nszbig1#
您已经启动了子进程
sqlcmd
,sqlcmd
输出一个提示符,接收您的命令,处理每个命令并输出另一个提示符。sqlcmd
进程正在等待更多的命令,但是您在send()
之后没有发送更多的命令。此时,您的response()
调用陷入了一个阻塞循环,试图读取最后一个提示符之后的字符。这意味着response()
将永远不会正常退出-即使它已经处理了一些命令并附加到StringBuilder
。为了更清楚地看到这一点,修复了
response()
中的一个小错误,即String.valueOf()
中数组的大小不正确,并添加了一个System.out
来告诉你response()
到目前为止已经读取了什么:重新运行,您应该看到
isr.read(array)
HAS工作正常,并且应该打印出select * from spt_monitor
的结果,但在打印提示符后,将在下一个或下一个isr.read(array)
调用时阻塞-并且response()
永远不会退出,因为没有接收到更多要处理的命令。除非您向
sqlcmd
发送退出命令或终止STDIN(这将导致sqlcmd
进程结束),否则将不再处理STDOUT-这两种情况都意味着response()
可以正常退出。通过在
send()
末尾或调用send()
后添加process.getOutputStream().close()
来终止STDIN,应该能够使response()
工作。但是,这意味着sqlcmd
将退出。