You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 22:45:04