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

如何从Java程序调用带输入输出重定向的C可执行程序mylexer?

在Java中调用外部可执行文件mylexer并处理输入输出的正确方式

你当前的代码里用了<和>这种shell重定向符号,但ProcessBuilder并不会解析这些符号——它只会把每个元素当作命令的独立参数,所以mylexer会把<、path、>、output.txt都当成普通的命令行参数,而不是用来重定向输入输出的指令,这肯定达不到你想要的效果。另外还要注意路径问题:你的mylexer在Project/Lexer目录下,而Java代码在Project/Parser里,直接写"mylexer"可能会找不到这个可执行文件,需要用相对路径(比如../Lexer/mylexer)或者绝对路径来指定。

下面给你两种可行的解决方案:

方案一:直接通过Java处理输入输出(推荐,无需中间文件)

这种方式不需要生成output.txt,直接把文件内容传给mylexer的标准输入,然后读取它的标准输出,更灵活也避免了额外的文件IO开销。

public static String getTokensFromFile(String path) {
    StringBuilder result = new StringBuilder();
    // 根据项目结构指定mylexer的相对路径
    String lexerPath = "../Lexer/mylexer";

    try {
        ProcessBuilder pb = new ProcessBuilder(lexerPath);
        Process process = pb.start();

        // 向mylexer的标准输入写入目标文件内容
        try (OutputStream os = process.getOutputStream();
             FileInputStream fis = new FileInputStream(path)) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = fis.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.flush();
            os.close(); // 关闭输入,告知mylexer输入结束
        }

        // 读取mylexer输出的结果
        try (InputStream is = process.getInputStream();
             BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
            String line;
            while ((line = reader.readLine()) != null) {
                result.append(line).append(System.lineSeparator());
            }
        }

        // 等待mylexer执行完成,检查退出码判断是否执行成功
        int exitCode = process.waitFor();
        if (exitCode != 0) {
            // 读取错误流排查问题
            try (InputStream err = process.getErrorStream();
                 BufferedReader errReader = new BufferedReader(new InputStreamReader(err))) {
                StringBuilder errorMsg = new StringBuilder();
                String line;
                while ((line = errReader.readLine()) != null) {
                    errorMsg.append(line).append(System.lineSeparator());
                }
                throw new RuntimeException("mylexer执行失败,退出码:" + exitCode + ",错误信息:" + errorMsg);
            }
        }

    } catch (IOException | InterruptedException e) {
        e.printStackTrace();
        throw new RuntimeException("调用mylexer时发生错误", e);
    }

    return result.toString().trim();
}

方案二:通过shell执行重定向(适合依赖shell特性的场景)

如果你一定要用<和>的重定向逻辑,可以让ProcessBuilder调用系统shell,把整个命令作为参数传递给shell执行,注意区分系统类型:

类Unix系统(Linux/macOS)

public static String getTokensFromFile(String path) {
    StringBuilder result = new StringBuilder();
    String lexerPath = "../Lexer/mylexer";
    String outputPath = "output.txt"; // 建议用绝对路径避免工作目录问题

    try {
        // 用bash -c 执行完整的shell命令
        String[] command = {"/bin/bash", "-c", lexerPath + " < " + path + " > " + outputPath};
        ProcessBuilder pb = new ProcessBuilder(command);
        Process process = pb.start();

        // 等待执行完成并检查退出码
        int exitCode = process.waitFor();
        if (exitCode != 0) {
            try (InputStream err = process.getErrorStream();
                 BufferedReader errReader = new BufferedReader(new InputStreamReader(err))) {
                StringBuilder errorMsg = new StringBuilder();
                String line;
                while ((line = errReader.readLine()) != null) {
                    errorMsg.append(line).append(System.lineSeparator());
                }
                throw new RuntimeException("mylexer执行失败,退出码:" + exitCode + ",错误信息:" + errorMsg);
            }
        }

        // 读取生成的output.txt内容
        try (BufferedReader reader = new BufferedReader(new FileReader(outputPath))) {
            String line;
            while ((line = reader.readLine()) != null) {
                result.append(line).append(System.lineSeparator());
            }
        }

    } catch (IOException | InterruptedException e) {
        e.printStackTrace();
        throw new RuntimeException("调用mylexer时发生错误", e);
    }

    return result.toString().trim();
}

Windows系统

把命令改成调用cmd.exe /c即可:

String[] command = {"cmd.exe", "/c", lexerPath + " < " + path + " > " + outputPath};

额外注意事项

  • 工作目录验证:可以通过System.getProperty("user.dir")查看Java程序的当前工作目录,确保相对路径的正确性。
  • 权限问题:类Unix系统下要给mylexer添加可执行权限,执行chmod +x mylexer即可。
  • 错误流处理:一定要读取Process的错误流,否则如果mylexer执行出错,错误信息会被缓冲,可能导致程序挂起或无法排查问题。

内容的提问来源于stack exchange,提问作者Jacobo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:47:35