javafx程序启动cmd.exe调用其他软件或者脚本指令

举个例子

ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", command);

pb.directory(new File( ConfigContextUtils.pdiConfig.getPdiHome()));

pb.start();

解释下这三句

1.ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", command);

作用:创建进程构建器,准备执行外部命令

// 分解参数: "cmd.exe" // 调用 Windows 命令行解释器"/c" // 参数:执行完命令后关闭 cmd 窗口command // 要执行的具体命令字符串 // 示例:如果 command = "dir C:\\" // 实际执行:cmd.exe /c "dir C:\\"

详细说明:

  • ProcessBuilder是 Java 中用于创建操作系统进程的类

  • cmd.exe是 Windows 的命令行程序

  • /c参数告诉 cmd:执行后面的命令,然后退出

  • 如果不加/c,cmd 会保持打开状态等待用户输入

等价于手动操作:

cmd

开始菜单 → 运行 → cmd.exe → 输入命令 → 回车
2.pb.directory(new File(ConfigContextUtils.pdiConfig.getPdiHome()));

作用:设置进程的工作目录

// 分解: ConfigContextUtils.pdiConfig.getPdiHome() // 从配置获取 PDI 安装路径 new File(...) // 创建 File 对象表示目录pb.directory(...) // 设置进程的工作目录

为什么重要:
假设getPdiHome()返回"D:\dev_install\pdi-ce-9.4.0.0-343\data-integration"

// 设置前:默认使用 Java 程序的当前目录 // 设置后:进程的工作目录变为 PDI 的安装目录必要性:
  • carte.batspoon.bat等批处理文件通常需要在其所在目录执行

  • 这些批处理文件内部可能使用了相对路径

  • 设置正确的工作目录可以避免 "找不到文件" 的错误

示例:

// 假设命令是 "carte.bat 127.0.0.1 8819" // 不设置 directory:在 Java 程序目录找 carte.bat(通常找不到) // 设置 directory:在 PDI 安装目录找 carte.bat(能找到)

3.pb.start();

作用:启动进程并异步执行

// start() 方法: // 1. 创建新的操作系统进程 // 2. 执行指定的命令 // 3. 立即返回,不等待进程结束 // 4. 返回 Process 对象用于控制进程

关键特性:

  • 异步执行:不会阻塞当前 Java 线程

  • 返回 Process 对象:可以控制进程(如等待结束、获取输出、终止进程等)

  • 独立进程:在操作系统中独立运行

完整示例与解释

原始代码:

ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", command); pb.directory(new File(ConfigContextUtils.pdiConfig.getPdiHome())); pb.start();

假设配置:

ConfigContextUtils.pdiConfig.getPdiHome() = "D:\\pdi\\data-integration" command = "carte.bat 127.0.0.1 8819"

实际执行效果:

// 1. 创建 ProcessBuilder // 相当于告诉系统:"我要执行 cmd.exe,参数是 /c 和 carte.bat ..." // 2. 设置工作目录为 D:\pdi\data-integration // 相当于先执行 "cd /d D:\pdi\data-integration" // 3. 启动进程 // 系统实际执行: // cmd.exe /c "cd /d D:\pdi\data-integration && carte.bat 127.0.0.1 8819"

重要补充:需要处理的几个问题

问题1:需要等待进程执行并获取输出

当前代码的问题:

pb.start(); // 只是启动,不等待完成,也看不到输出

改进版本:

Process process = pb.start(); // 获取输出流(进程的标准输出) try (BufferedReader reader = new BufferedReader( new InputStreamReader(process.getInputStream(), "GBK"))) { String line; while ((line = reader.readLine()) != null) { System.out.println("输出: " + line); // 显示命令输出 } } // 等待进程结束 int exitCode = process.waitFor(); System.out.println("进程结束,退出码: " + exitCode);

问题2:需要处理错误流

防止进程卡住:

Process process = pb.start(); // 必须读取错误流,否则缓冲区满时进程会挂起 new Thread(() -> { try (BufferedReader errorReader = new BufferedReader( new InputStreamReader(process.getErrorStream(), "GBK"))) { String line; while ((line = errorReader.readLine()) != null) { System.err.println("错误: " + line); } } catch (IOException e) { e.printStackTrace(); } }).start();

问题3:处理带空格的路径

如果路径包含空格:

// 错误:路径有空格会被拆分成多个参数 String command = "carte.bat \"C:\\Program Files\\pdi\" args"; // 正确:需要将整个命令作为单个字符串传递 ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", command);

完整的安全版本

public static void startPDIService(String serviceType) { String pdiHome = ConfigContextUtils.pdiConfig.getPdiHome(); String host = ConfigContextUtils.pdiConfig.getCarteHost(); String port = ConfigContextUtils.pdiConfig.getCartePort(); // 构建命令 String command; if ("carte".equals(serviceType)) { command = String.format("chcp 65001 && set JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF-8 && carte.bat %s %s", host, port); } else { command = "chcp 65001 && set JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF-8 && spoon.bat"; } try { ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", command); pb.directory(new File(pdiHome)); // 设置工作目录 // 启动进程 Process process = pb.start(); // 启动线程读取输出(防止阻塞) startOutputReader(process); // 启动线程读取错误(防止阻塞) startErrorReader(process); // 可以记录进程ID供后续管理 System.out.println(serviceType + " 进程已启动,PID可通过其他方式获取"); } catch (IOException e) { e.printStackTrace(); } } private static void startOutputReader(Process process) { new Thread(() -> { try (BufferedReader reader = new BufferedReader( new InputStreamReader(process.getInputStream(), "GBK"))) { String line; while ((line = reader.readLine()) != null) { System.out.println("输出: " + line); } } catch (IOException e) { // 进程可能已结束,正常关闭流 } }).start(); } private static void startErrorReader(Process process) { new Thread(() -> { try (BufferedReader reader = new BufferedReader( new InputStreamReader(process.getErrorStream(), "GBK"))) { String line; while ((line = reader.readLine()) != null) { System.err.println("错误: " + line); } } catch (IOException e) { // 进程可能已结束,正常关闭流 } }).start(); }

总结

你的三行代码:

  1. 创建命令:告诉系统执行什么

  2. 设置目录:告诉系统在哪里执行

  3. 启动进程:开始执行命令

这是一个标准的、正确的启动外部进程的方式,特别适合启动 PDI 这种需要特定工作目录的程序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1206493.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何解决 Spoon 与 Carte 互联的 UTF-8 编码问题

问题背景 在 Windows 10 环境下配置 PDI 9.4,使用 Spoon 连接 Carte 服务器时遇到以下问题: HTTP 400 Bad Request - Invalid byte 2/3 of 2/3-byte UTF-8 sequence Spoon 无法连接到 Carte 服务器 转换文件无法远程执行 根本原因 Windows 系统默认…

spoon如何连接carte如何将.ktr任务或者.kjb任务提交个远程carte服务让,carte的服务端来执行 etl脚本的任务呢?

前提是你的carte远程服务已经启动了 第一步打开 spoon,打开文件选中你的.ktr或者.kjb 第二步spoon与carte服务的通信连接配置,就是通过.ktr任务配置文件的子服务器选项来配置 第三步 对.ktr任务进行运行时配置 .ktr有两种运行模式 第一种 Pentaho loc…

Pentaho Data Integration:Spoon与Carte的对比

在数据集成和ETL(Extract, Transform, Load)任务中,Pentaho Data Integration(PDI)是一个强大的工具。PDI提供了两个主要的组件:Spoon和Carte,它们在执行转换(.ktr 文件)…

mast3r-smf测试 - MKT

mast3r-smf测试 1 关闭代理# 清除代理环境变量unset http_proxy https_proxy all_proxy HTTP_PROXY HTTPS_PROXY ALL_PROXY # 运行MASt3R demopython3 demo.py \ --model_name checkpoints/MASt3R_ViTLarge_BaseDe…

备份 还原 系统 数据保护

操作系统备份直接找方案厂商给备份方案:硬件还原卡冰点还原Acronis True Image(克隆与恢复软件)Acronis备份还原方案http://www.tieten.cnhttp://www.acronis.com/en-us影子系统赛门铁克傲梅 http://www.disktool.cn/…

nodejs基于vue的教学质量评价管理系统的设计与实现 评教系统39j06

文章目录摘要关键词--nodejs技术栈--结论源码文档获取/同行可拿货,招校园代理 :文章底部获取博主联系方式!摘要 该系统基于Node.js和Vue.js构建,旨在实现高校教学质量评价的数字化管理。后端采用Node.js的Express框架提供RESTful API接口&am…

中小厂 AI 招聘隐藏要求:除了技术,这 2 点更关键

在AI人才竞争白热化的当下,中小厂往往无法像大厂那样比拼薪资福利与品牌光环,其招聘逻辑也更贴近业务本质。多数求职者误以为只要夯实Python、TensorFlow等技术栈,就能顺利通关,但实际上面试官在技术达标后,会更看重两…

二叉树递归实现

二叉树链式结构的实现详解(C语言) 前置说明 在学习二叉树的基本操作前,需先创建一棵二叉树。为降低学习成本,我们手动快速构建一棵简单二叉树,待掌握基本操作后再深入研究真正的创建方式(如通过前序序列构…

nodejs基于vue的教师科研项目申报信息管理系统的设计与实现_c7z6m

文章目录设计背景技术架构核心功能创新点实现效果--nodejs技术栈--结论源码文档获取/同行可拿货,招校园代理 :文章底部获取博主联系方式!设计背景 教师科研项目申报信息管理系统旨在简化科研项目申报流程,提高管理效率。系统基于Node.js后端…

nodejs基于vue二手商品物品商城网站_s926p

文章目录 基于Node.js与Vue的二手商品商城网站摘要技术栈核心功能部署与优化扩展性 --nodejs技术栈--结论源码文档获取/同行可拿货,招校园代理 :文章底部获取博主联系方式! 基于Node.js与Vue的二手商品商城网站摘要 技术栈 后端框架: Node.js (Express…

nodejs基于vue基于MVC模式的考研论坛互动交流系统的私信设计与实现

文章目录 考研论坛私信系统的设计与实现摘要 --nodejs技术栈--结论源码文档获取/同行可拿货,招校园代理 :文章底部获取博主联系方式! 考研论坛私信系统的设计与实现摘要 背景与目标 考研论坛作为信息交流平台,需高效安全的私信功能支持用户间…

nodejs基于vue技术人人美食菜谱分享点餐配送平台的设计与实现

文章目录 摘要内容技术实现要点创新点与价值 --nodejs技术栈--结论源码文档获取/同行可拿货,招校园代理 :文章底部获取博主联系方式! 摘要内容 该平台基于Node.js与Vue.js技术栈,构建了一个集美食菜谱分享、在线点餐及配送服务于一体的综合性…

税筹园区助力企业合规减负与税务优化

税筹园区的作用在于为企业提供税务筹划的有效平台,使其能够以更低的成本合规经营。特捷税在江苏徐州的园区模式,让企业能够享受到增值税垫付及各类税收优惠,显著降低了运营负担。企业通过参与园区,不仅能快速获得专业合规支持&…

气体涡轮流量计 本土精造 精准守护气体管控

2019年,大连格恩朗扎根滨城,承袭本土工业测控技术积淀,深耕气体计量领域,打造适配北方严寒、工业复杂环境的气体涡轮流量计。以“稳定精准、耐用易管”为核心,严守国家工业计量标准,覆盖燃气供应、工业气体…

企业级邮件服务优化实战:从550错误到高可用架构

本文将通过实战案例,分享如何从零构建一个稳定、高效、可扩展的企业级邮件服务架构。 一、问题诊断:550错误背后的真相 1.1 常见的邮件发送问题 java // 问题代码示例:简单的邮件发送方法 public class ProblematicEmailSender {public b…

格恩朗金属管浮子流量计 本土精造 稳控流体计量

2019年,大连格恩朗扎根滨城,承袭本土工业测控领域的技术积淀,专注打造适配北方复杂工况的金属管浮子流量计。以“稳定耐用、精准计量”为核心,遵循国家工业计量标准,覆盖化工生产、环保处理、能源输送等多场景&#xf…

Excel动态生成SQL更新语句:批量处理数据的高效技巧

在日常数据处理和数据库维护工作中,我们经常需要将Excel中的数据转换为SQL语句进行批量操作。特别是当需要根据Excel表格中的数据更新数据库记录时,手动编写每一条SQL语句既耗时又容易出错。本文将详细介绍如何使用Excel公式高效地生成"update"…

救命神器9个AI论文平台,自考学生轻松搞定毕业论文!

救命神器9个AI论文平台,自考学生轻松搞定毕业论文! AI 工具助力论文写作,自考学生迎来新希望 在当今信息化快速发展的时代,AI 技术正以前所未有的速度改变着我们的学习方式。对于自考学生而言,撰写毕业论文是一项既重要…

vLLM 推理 GPU 选型指南:显存、KV Cache 与性能瓶颈全解析

为 vLLM 推理有效规划 GPU 规模并进行合理配置,首先需要清晰理解大语言模型处理的两个基本阶段——Prefill(预填充)和 Decode(解码),以及这两个阶段对硬件提出的不同需求。 本指南深入剖析了 vLLM 运行时行…

详解redis(7):数据结构List

一、List 是什么?Redis List 的本质有序的字符串序列,按插入顺序排列,两端操作快你可以把它理解成:双端队列支持:左边进 / 左边出右边进 / 右边出二、Redis 早期 List 的两种底层结构Redis 的哲学:小数据用…