如何使用while循环向Java ProcessBuilder进程输入值并获取输出
实现方案
核心实现逻辑如下:
- 开启进程前先配置ProcessBuilder合并错误流,避免缓冲区阻塞导致进程挂死
- 进程启动后一次性获取对应外部程序stdin的输入流、对应stdout的输出流的包装类,避免重复创建开销
- 循环内每次写入文件名后自动追加换行,直接读取返回的一行结果即可完成单次交互
- 所有文件处理完成后发送quit指令,等待进程正常退出后再写入CSV文件
修改后的完整代码如下:
import java.io.*; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Stack; // 原有类定义此处省略 public void getNum(RoutingContext context) { String command = context.getBodyAsJson().getString("command"); if (command.equals("ok")) { BufferedReader processReader = null; PrintWriter processWriter = null; BufferedWriter csvWriter = null; try { File folder = new File("/usr/local/bin/pic"); ArrayList<String[]> toCsv = new ArrayList<>(); File[] listOfFiles = folder.listFiles(); // 判空避免空指针异常 if (listOfFiles == null || listOfFiles.length == 0) { log.info("目标目录未找到有效文件"); return; } Stack<String> fileStack = new Stack<>(); for (File file : listOfFiles) { // 过滤子目录,仅处理文件 if (file.isFile()) { fileStack.push(file.getAbsolutePath()); } } ProcessBuilder pb = new ProcessBuilder("/bin/bash", "-c", "./TestELANPRv2.2"); File dir = new File("/usr/local/elanpr-src"); pb.directory(dir); // 合并错误流到标准输出,避免缓冲区占满导致进程卡住 pb.redirectErrorStream(true); Process process = pb.start(); // 初始化流,开启自动刷新无需每次手动调用flush processWriter = new PrintWriter(new OutputStreamWriter(process.getOutputStream(), StandardCharsets.UTF_8), true); processReader = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8)); while(!fileStack.isEmpty()){ String fileName = fileStack.pop(); // 写入文件名+换行,等价于手动输入后按回车 processWriter.println(fileName); // 读取外部程序返回的结果 String result = processReader.readLine(); if (result != null) { toCsv.add(new String[]{fileName, result}); } } // 发送退出指令 processWriter.println("quit"); // 等待进程正常退出 process.waitFor(); // 写入CSV文件,存储路径可自行调整 File csvFile = new File("/usr/local/elanpr-src/result.csv"); csvWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(csvFile), StandardCharsets.UTF_8)); // 写入CSV表头 csvWriter.write("文件名,识别结果"); csvWriter.newLine(); for (String[] row : toCsv) { // 简单处理含逗号的字段,用双引号包裹避免CSV格式错乱 String fileName = row[0].contains(",") ? "\"" + row[0] + "\"" : row[0]; String result = row[1].contains(",") ? "\"" + row[1] + "\"" : row[1]; csvWriter.write(fileName + "," + result); csvWriter.newLine(); } csvWriter.flush(); log.info("CSV文件生成完成,总记录数:" + toCsv.size()); } catch (Exception e) { e.printStackTrace(); log.info("Error.Running.CMD: " + e.getMessage()); } finally { // 统一关闭所有流 try { if (processWriter != null) processWriter.close(); if (processReader != null) processReader.close(); if (csvWriter != null) csvWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } }
注意事项
- 如果外部程序的输出编码不是UTF-8,需要修改流初始化时的编码参数为对应编码,否则会出现乱码
- 如果外部程序每次返回结果不止一行,需要调整读取逻辑,根据实际返回格式判断单次结果的结束标记
- 处理大文件量时若出现卡顿,可添加超时逻辑判断进程是否异常挂死
内容的提问来源于stack exchange,提问作者user17085185
相关产品推荐
相关产品推荐

