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

如何在Java ProcessBuilder中实现输入重定向?

实现Linux cat << END > output 等效的Java ProcessBuilder功能

问题背景

我已经通过Java ProcessBuilder实现了将Linux cat命令的输出重定向到文件,代码如下:

// read x.txt with cat and redirect the output to output.txt
public static void main (String args []) throws Exception
{
    List <String> params = new ArrayList <String> ();
    params.add ("cat");
    params.add ("x.txt");       
    ProcessBuilder pb = new ProcessBuilder (params);
    pb.redirectOutput (new File ("output.txt"));
    Process p = pb.start ();
    p.waitFor (3, TimeUnit.SECONDS);
    System.out.println ("exit="+p.exitValue());
}

现在希望实现类似Linux中cat << END > output的Here Document输入重定向功能,但尝试的代码执行后返回状态码1(成功应为0)或无法结束:

public static void main (String args []) throws Exception
{
    List <String> params = new ArrayList <String> ();
    params.add ("cat");
    params.add ("/dev/stdin");
    params.add ("<<");
    params.add ("END");
    
    ProcessBuilder pb = new ProcessBuilder (params);
    pb.redirectOutput (new File ("output.txt"));
    Process p = pb.start ();
    OutputStream os = p.getOutputStream ();
    os.write ("\nblabla\nEND\n".getBytes ());
    p.waitFor (3, TimeUnit.SECONDS);
    System.out.println ("exit="+p.exitValue());
}

错误原因

<< END是Shell的Here Document重定向语法,并不是cat命令的合法参数。直接把<<和END传给cat时,cat会将它们当作要读取的文件名,而这些文件实际不存在,因此cat会报错返回状态码1;同时cat会一直等待读取不存在的文件,导致进程无法正常结束。

正确实现方案

方案1:通过Shell执行完整命令

直接调用Shell(如bash)来解析包含Here Document的命令,让Shell处理重定向逻辑:

public static void main(String args[]) throws Exception {
    List<String> params = new ArrayList<>();
    params.add("bash");
    params.add("-c");
    // 将完整的Shell命令作为参数传递,包含Here Document内容
    params.add("cat << END > output.txt\nblabla\nEND");

    ProcessBuilder pb = new ProcessBuilder(params);
    Process p = pb.start();

    boolean isFinished = p.waitFor(3, TimeUnit.SECONDS);
    if (isFinished) {
        System.out.println("exit=" + p.exitValue());
    } else {
        p.destroy();
        System.out.println("进程超时终止");
    }
}

方案2:直接向cat的标准输入写入内容

cat命令在不带任何参数时,默认会读取标准输入。因此可以直接向Process的输出流(对应cat的标准输入)写入内容,写完后关闭流告知cat输入结束:

public static void main(String args[]) throws Exception {
    List<String> params = new ArrayList<>();
    params.add("cat");
    // 无参数时cat默认读取标准输入

    ProcessBuilder pb = new ProcessBuilder(params);
    pb.redirectOutput(new File("output.txt"));
    Process p = pb.start();

    // 使用try-with-resources自动关闭输出流,告知cat输入结束
    try (OutputStream os = p.getOutputStream()) {
        os.write("blabla\n".getBytes());
    }

    boolean isFinished = p.waitFor(3, TimeUnit.SECONDS);
    if (isFinished) {
        System.out.println("exit=" + p.exitValue());
    } else {
        p.destroy();
        System.out.println("进程超时终止");
    }
}

两种方案对比:

  • 方案1适合需要使用复杂Shell语法的场景,依赖Shell进程解析命令;
  • 方案2更轻量,直接与cat进程交互,无需启动额外的Shell进程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 13:17:05