如何通过ProcessBuilder使用BufferedReader和BufferedWriter与进程控制台交互?
文本版BlackJack机器人写入操作无响应问题排查与修复
我开发了一款文本版BlackJack游戏,正在编写机器人程序自动游玩并记录结果。目前已成功启动游戏进程并读取控制台初始数据,但机器人确定操作后,既无法将操作写入游戏控制台,也无法获取游戏返回的响应。
当前代码如下:
public static void main(String[] args) { try { ProcessBuilder builder = new ProcessBuilder("java","app.App"); builder.directory(new File("C:\\Users\\damon\\OneDrive\\school\\code\\BlackJack")); builder.redirectErrorStream(true); Process process = builder.start(); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream())); String line1 = reader.readLine(); // Player's total String line2 = reader.readLine(); // Player's cards String line3 = reader.readLine(); // Can split String line4 = reader.readLine(); // Dealer's total String line5 = reader.readLine(); // Dealer's cards // Process the lines to extract and store the data int playersTotal = Integer.parseInt(line1); String[] playerCards = line2.split(" "); boolean canSplit = line3.equals("s"); int dealersTotal = Integer.parseInt(line4); String[] dealerCards = line5.split(" "); Stratergy strat=new Stratergy(playersTotal, playerCards[0], canSplit,dealersTotal); writer.write(strat.suggestAction()+"\n"); System.out.println(line1+"\n"+line2+"\n"+line3+"\n"+line4+"\n"+line5+"\n"+strat.suggestAction()); System.out.println(reader.readLine()); reader.close(); } catch (IOException e) { e.printStackTrace(); } }
问题根源分析
- 缓冲输出未刷新:
BufferedWriter的write()方法会把数据暂存在缓冲区,没有直接发送给子进程,游戏根本没收到操作指令。 - 资源关闭时机错误:读取响应前就关闭了
reader,导致后续读取操作直接失败。 - 未处理交互阻塞:如果游戏有持续输出,主线程可能因等待输入而卡住,影响交互流程。
修复后的代码
public static void main(String[] args) { Process process = null; BufferedReader reader = null; BufferedWriter writer = null; try { ProcessBuilder builder = new ProcessBuilder("java", "app.App"); builder.directory(new File("C:\\Users\\damon\\OneDrive\\school\\code\\BlackJack")); builder.redirectErrorStream(true); process = builder.start(); reader = new BufferedReader(new InputStreamReader(process.getInputStream())); writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream())); // 读取初始游戏数据 String line1 = reader.readLine(); String line2 = reader.readLine(); String line3 = reader.readLine(); String line4 = reader.readLine(); String line5 = reader.readLine(); // 解析数据 int playersTotal = Integer.parseInt(line1); String[] playerCards = line2.split(" "); boolean canSplit = line3.equals("s"); int dealersTotal = Integer.parseInt(line4); // 获取策略操作 Stratergy strat = new Stratergy(playersTotal, playerCards[0], canSplit, dealersTotal); String action = strat.suggestAction(); // 写入操作并强制刷新缓冲区,确保游戏收到指令 writer.write(action + "\n"); writer.flush(); // 调试输出 System.out.println(line1 + "\n" + line2 + "\n" + line3 + "\n" + line4 + "\n" + line5 + "\n" + action); // 读取游戏响应 String response = reader.readLine(); if (response != null) { System.out.println("游戏返回:" + response); } else { System.out.println("未收到响应,游戏进程可能已终止"); } } catch (IOException e) { e.printStackTrace(); } finally { // 按顺序关闭资源,避免泄漏 try { if (writer != null) writer.close(); if (reader != null) reader.close(); if (process != null) process.destroy(); } catch (IOException e) { e.printStackTrace(); } } }
额外优化建议
- 分离输入输出线程:如果游戏是多轮交互,单独开线程处理读取输出,避免主线程因等待输入阻塞,比如用一个线程循环读取游戏输出并打印,主线程专注发送操作指令。
- 适配换行符:Windows环境下部分程序需要
\r\n作为换行符,可尝试替换writer.write(action + "\n")为writer.write(action + "\r\n")。 - 检查进程状态:用
process.isAlive()判断游戏进程是否存活,排查是否进程意外退出导致无响应。
内容的提问来源于stack exchange,提问作者Damon
相关产品推荐
相关产品推荐

