简介
有时候需要跟cmd/shell程序交互,实时读取响应流。
方法
windows平台需要先切换utf8编码(chcp 65001
),这里使用的是processBuilder.start()方式来执行shell,可以非阻塞的方式持续获取控制台上的输出流。如果使用的是Runtime.getRuntime().exec(“”).getInputStream()则会先阻塞至命令执行完成后,才会返回控制台上的内容。
public void execShell() {
ProcessBuilder processBuilder = getProcessBuilder(question, isWindows);
// 启动进程并执行命令
Process p = processBuilder.start();
InputStream is = p.getInputStream();
InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
try (BufferedReader br = new BufferedReader(isr)) {
// windows平台第一行输出为切换编码成功
if (isWindows) {
br.readLine();
}
int len = -1;
char[] buf = new char[512];
StringBuilder builder = new StringBuilder();
ChatResponse.Data data = new ChatResponse.Data();
data.setSession_id(sessionId);
Result<ChatResponse.Data> result = Results.success(data);
while ((len = br.read(buf)) > 0) {
builder.append(new String(buf, 0, len));
data.setChat_result(builder.toString());
emitter.send(result);
}
}
// 等待命令执行完成
p.waitFor();
}
// 判断是否是window平台
private boolean isWindows() {
String osName = System.getProperty("os.name").toLowerCase();
return osName.contains("win");
}
private ProcessBuilder getProcessBuilder(String cmd, boolean isWindows) {
question = question.replaceAll("\n", "\\\\n");
if (isWindows) {
return new ProcessBuilder("cmd.exe", "/c", "chcp 65001 &&" + cmd);
} else {
// linux
return new ProcessBuilder("/bin/sh", "-c", cmd);
}
}