Java如何模拟命令< file.txt输入重定向 适配mysql等命令调用场景
解决方案
现有代码失效原因
- 使用
Scanner.nextLine()读取文件行时会自动丢弃行尾的换行符,仅调用stdin.write(line)不会写入换行,导致子进程收到的输入是无换行的连续内容,无法正常解析,这是核心问题。 - 未消费子进程的标准输出和错误输出,可能导致子进程因为输出缓冲区满被阻塞,无法正常执行结束。
最简实现方案(Java 7及以上)
无需自行实现IO拷贝逻辑,ProcessBuilder已原生支持输入重定向,完全等效于命令行的< file.txt效果,适配你调用mysql的场景示例如下:
// 按参数拆分命令,避免空格等特殊字符导致的解析错误 ProcessBuilder pb = new ProcessBuilder("mysql", "-u", "你的用户名", "-p你的密码", "目标数据库名"); // 直接将source文件重定向为子进程的标准输入 pb.redirectInput(source); // 可选:将子进程的输出、错误输出重定向到当前进程的对应流,避免缓冲区阻塞 pb.redirectOutput(ProcessBuilder.Redirect.INHERIT); pb.redirectError(ProcessBuilder.Redirect.INHERIT); Process process = pb.start(); int ret = process.waitFor();
原有代码修复方案(兼容更早版本)
如果需要保留自行写流的逻辑,修复后代码如下:
String commandLine = "myCommand"; Process process = Runtime.getRuntime().exec(commandLine); // 写入标准输入的线程 new Thread(() -> { try (BufferedWriter stdin = new BufferedWriter(new OutputStreamWriter(process.getOutputStream())); Scanner scanner = new Scanner(source) ){ String line; while (scanner.hasNextLine()) { line = scanner.nextLine(); stdin.write(line); stdin.newLine(); // 补充写入行尾换行符 System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } }).start(); // 消费子进程输出的线程,避免缓冲区阻塞 new Thread(() -> { try (InputStream stdout = process.getInputStream(); InputStream stderr = process.getErrorStream()) { stdout.transferTo(System.out); stderr.transferTo(System.err); } catch (IOException e) { e.printStackTrace(); } }).start(); int ret = process.waitFor();
内容的提问来源于stack exchange,提问作者Fpasquer
相关产品推荐
相关产品推荐

