我使用JAVA swing做了一个命令行工具:
使用的核心技术是SwingWorker,运行效果:
核心工具类:
public class ShellSwingWorker extends SwingWorker<Boolean, Character> { /*** * 执行命令的正常输出(对程序来说是输入) */ private BufferedReader br_right = null; /*** * 执行命令的错误输出(对程序来说是输入) */ private BufferedReader br_error = null; /*** * 进程封装类 */ private MyProcess myprocess = null; private char word = ' '; private int tmp = 0; private boolean isPrintVerbose = false; private StringBuffer stringbuf = new StringBuffer(); private JTextPane resultTP = null; /*** * result textarea' document */ private Document docment; /*** * charset of result */ private String encoding; /*** * logging */ protected Logger logger = Logger.getLogger(this.getClass()); /*** * 命令前缀 */ public ShellSwingWorker(MyProcess myprocess, BufferedReader br) { this.br_right = br; this.myprocess = myprocess; } /*** * 构造方法. * * @param process * @param textPane * @param encoding */ public ShellSwingWorker(Process process, JTextPane textPane, String encoding) { MyProcess proc = null; proc=new MyProcess(process); construct(proc,textPane,encoding); } /*** * 构造方法. * * @param myprocess * @param textPane * @param encoding */ public ShellSwingWorker(MyProcess myprocess, JTextPane textPane, String encoding) { construct(myprocess, textPane, encoding); } private void construct(MyProcess myprocess, JTextPane textPane, String encoding){ this.myprocess = myprocess; if (ValueWidget.isNullOrEmpty(encoding)) { encoding = SystemHWUtil.CURR_ENCODING; } this.encoding = encoding; try { br_right = new BufferedReader(new InputStreamReader( myprocess.getInputStream(), this.encoding), 4096); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } try { br_error = new BufferedReader(new InputStreamReader( myprocess.getErrorStream(), this.encoding), 4096); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } this.resultTP = textPane; docment = this.resultTP.getDocument(); } @Override protected Boolean doInBackground() throws Exception { while ((tmp = br_right.read()) != -1) { word = (char) tmp; publish(word); } while ((tmp = br_error.read()) != -1) { word = (char) tmp; publish(word); } if (isPrintVerbose)// 是否打印详细信息 { System.out.println("doInBackground() over"); } return true; } @Override protected void process(List<Character> chunks) { for (char temp : chunks) { { // System.out.print(temp); // this.resultTP.setText(this.stringbuf.toString());//效率低 int leng2 = this.stringbuf.length(); try { // 追加 docment.insertString(leng2, String.valueOf(temp), null); } catch (BadLocationException e) { GUIUtil23.warningDialog(e.getMessage()); e.printStackTrace(); } this.stringbuf.append(temp); } } } public StringBuffer getStringbuf() { return stringbuf; } /*** * main thread can't execute next command(below waitFor()) until done() is * executed;if done() hasn't be executed,this.myprocess.waitFor() will wait */ @Override protected void done() { if (isPrintVerbose) { System.out.println("done() is executed"); } if (!ValueWidget.isNullOrEmpty(br_right)) { try { br_right.close(); br_error.close(); } catch (IOException e) { e.printStackTrace(); } } String logMesg=this.getClass().getSimpleName()+".done() is executed successfully."; logger.debug(logMesg); System.out.println(logMesg); this.myprocess.stopLoop(); } public MyProcess getProcess() { return myprocess; }
项目采用maven构建,结构如下:
笔记:
遇到的问题
(1)卡了?
<!--[if gte vml 1]><v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"> <v:stroke joinstyle="miter"/> <v:formulas> <v:f eqn="if lineDrawn pixelLineWidth 0"/> <v:f eqn="sum @0 1 0"/> <v:f eqn="sum 0 0 @1"/> <v:f eqn="prod @2 1 2"/> <v:f eqn="prod @3 21600 pixelWidth"/> <v:f eqn="prod @3 21600 pixelHeight"/> <v:f eqn="sum @0 0 1"/> <v:f eqn="prod @6 1 2"/> <v:f eqn="prod @7 21600 pixelWidth"/> <v:f eqn="sum @8 21600 0"/> <v:f eqn="prod @7 21600 pixelHeight"/> <v:f eqn="sum @10 21600 0"/> </v:formulas> <v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/> <o:lock v:ext="edit" aspectratio="t"/> </v:shapetype><v:shape id="图片_x0020_1" o:spid="_x0000_i1025" type="#_x0000_t75" style='width:340.5pt;height:328.5pt;visibility:visible'> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image001.png" o:title=""/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]--> |
为什么呢?确实是使用的线程啊?
原因:
@Override protectedvoid process(List<Character> chunks) { for (char temp : chunks) { { // System.out.print(temp); this.stringbuf.append(temp); this.resultTP.setText(this.stringbuf.toString());
} } } |
标红的代码影响性能
解决方法:
<!--[if gte vml 1]><v:shape id="图片_x0020_4" o:spid="_x0000_i1026" type="#_x0000_t75" style='width:414.75pt; height:227.25pt;visibility:visible'> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image003.png" o:title=""/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]--> |
swingwork中done()方法还没有完全执行完毕,就执行proc.waitFor()后面的语句
使用swingwork 可以在界面上异步的看到执行结果,而不是等待执行完之后才一次性打印出来,影响用户体验。这就是swingwork存在的目的。
解决方法:
对Process进行封装,看下面标黄的代码,若loop为true则会死循环,一直等待。
package com.common.util;
import java.io.InputStream; import java.io.OutputStream;
publicclass MyProcess extends Process { private Process proc; privatebooleanloop=true;
public Process getProc() { returnproc; }
publicboolean isLoop() { returnloop; }
/*** * should be invoked in end */ public int waitFor() throws InterruptedException{ int waitFor_exitcode= proc.waitFor(); /*must wait until ShellSwingWorker.done() is executed. */ while (loop) { Thread.sleep(100); } return waitFor_exitcode; }
publicvoid stopLoop(){ loop=false; }
public OutputStream getOutputStream(){ returnproc.getOutputStream(); }
public InputStream getInputStream(){ returnproc.getInputStream(); }
public InputStream getErrorStream(){ returnproc.getErrorStream(); } public int exitValue(){ returnproc.exitValue(); } public MyProcess(Process proc) { super(); this.proc = proc; }
@Override publicvoid destroy() { this.proc.destroy();
} }
|
那么时候终止循环呢?
在swingwork的done()方法中:
@Override protectedvoid done() { if (isPrintVerbose) { System.out.println("done() is executed"); } if (!ValueWidget.isNullOrEmpty(br_right)) { try { br_right.close(); br_error.close(); } catch (IOException e) { e.printStackTrace(); } } this.myprocess.stopLoop(); } |
下面是有问题的:
Process p3=pb.start(); ShellSwingWorker worker = new ShellSwingWorker(p3, resultTP, encoding); worker.execute(); Process proc = worker.getProcess(); p3.waitFor(); System.out.println("proc.waitFor() is executed."); // result2 = worker.getStringbuf().toString(); int exitCode2 = proc.exitValue(); |
执行结果:
<!--[if gte vml 1]><v:shape id="_x0000_i1027" type="#_x0000_t75" style='width:339pt;height:36pt'> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image005.png" o:title=""/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]--> |
下面的事正确的:
ShellSwingWorker worker = new ShellSwingWorker(pb.start(), resultTP, encoding); worker.execute(); Process proc = worker.getProcess(); proc.waitFor(); System.out.println("proc.waitFor() is executed."); // result2 = worker.getStringbuf().toString(); int exitCode2 = proc.exitValue(); |
执行结果如下:
<!--[if gte vml 1]><v:shape id="_x0000_i1028" type="#_x0000_t75" style='width:337.5pt;height:37.5pt'> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image007.png" o:title=""/> </v:shape><![endif]--><!--[if !vml]--><!--[endif]--> |
项目源代码见附件:sh_script_executor.zip
相关推荐
Java命令行辅助工具是一款专为Java开发者设计的小型应用程序,旨在简化Java源代码的编译和执行过程。在日常开发中,我们通常需要通过命令行界面(CLI)来操作Java程序,这包括编译`.java`源文件为`.class`字节码文件...
下面将对这些Java命令行工具进行详细的总结和说明。 一、基础工具(Basic Tools) 1. javac:Java编程语言的编译器。开发者使用它将.java源文件编译成.class字节码文件,以便能够在JVM上运行。 2. java:Java应用...
精品软件工具--圣天诺软锁的Java命令行工具:验证授权、获取授权信息、获取机器指纹信息、更新授权文件等
在创建命令行工具时,Java提供了丰富的类库,如`java.util.Scanner`用于用户输入处理,`java.io`包下的类用于文件操作,`java.lang.ProcessBuilder`可以调用系统命令,以及`java.nio`非阻塞I/O流等,这些都使得Java...
Java cmd命令行模拟工具是一种用于在Java环境中模拟操作系统命令行工具的实用程序。它使得开发者能够在Java代码中执行系统命令,获取命令输出,并对命令行交互进行控制,这对于自动化测试、脚本编写以及需要与系统...
Java命令行classpath(类路径)的设置是Java开发过程中的一项基础操作,对于理解和运行Java程序至关重要。类路径是指定Java虚拟机(JVM)在执行Java程序时查找类文件的位置。正确配置类路径能确保JVM能够找到并加载...
这是包装RythmTemplateEngine的简单Java命令行工具: 用法java -jar rythm-util [json string] rythm-util将[json字符串]解析为一个哈希映射,该映射映射在zhy2002.rythm.RythmContext对象中。 RythmContext为对象...
这份PDF文档详细列举并解释了Java命令行接口(JVM)的各种参数,旨在帮助开发者更好地理解和使用Java命令行工具。 Java命令通常以`java`或者`javac`为起点,其中`java`用于执行已编译的Java类文件,而`javac`则是...
这篇博客文章将探讨如何在Eclipse中配置和使用Java命令行参数,这对于理解程序的运行行为以及调试是非常有帮助的。 在Java程序中,命令行参数是通过`main`方法的`String[] args`数组传递的,它们允许我们在不修改...
Java命令行文件管理器是一款基于Java编程语言开发的实用工具,专为用户在终端环境中提供高效、便捷的文件操作体验。这款程序集成了多种文件管理功能,如创建、删除、重命名、拷贝文件,浏览目录,以及压缩与解压缩、...
调试器用于检查 maven 最新版本的 build.gradle 依赖项的 Java 命令行工具用法: ./java -jar depchecker-all-1.0.jar 构建可运行的 jar: ./gradlew fatJarJar 将位于 build/libs 注意:您必须使用 java 8 来构建...
CSV for Java是一个专为Java设计的开源库,它提供了方便的API以及命令行工具,使得开发者在处理CSV文件时能更加高效和灵活。 该库的核心功能包括: 1. **读取CSV文件**:CSV for Java提供了一套完整的API,允许...
本指南涵盖了JDK14的安装、配置、环境变量设置、Java命令行工具使用等方面的知识点。 安装JDK14 JDK14的安装分为两种方式:在线安装和离线安装。在线安装需要连接互联网,通过 Oracle 官方网站下载并安装JDK14。...
一个用于管理AVM炸弹盒父母控件的Java命令行工具 用法: java -jar <jar> -u <username> -p <password> -D <Device> -P 其他选项: -url默认为fritz.box -auth可能的选项是MD5 (默认)和PBKDF2 (新的炸弹盒)
使用JCmdLineProgress库,开发者可以方便地在Java命令行程序中集成进度条,提高用户体验。通过实例化库提供的类,设置参数,然后在执行任务时调用相应的更新方法,就可以实现动态的进度显示。 例如,以下是一个简单...
### Java中的命令行工具 在Java开发过程中,虽然现代IDE(如IntelliJ IDEA、Eclipse等)提供了非常丰富的功能,使得很多开发工作变得更加便捷,但掌握一些基本...希望本文能够帮助你更好地理解和使用Java命令行工具。
本文将详细讲解如何使用Java命令行工具下载微信支付API v3的平台证书。 微信支付API v3的平台证书是一个PEM格式的文件,包含了商户的私钥和公钥信息。在进行微信支付接口调用时,需要使用该证书来签名和验签,确保...
总的来说,"Java命令行应用开发"涵盖了Java编程的多个方面,包括语言基础、输入/输出、异常处理、文件操作、设计原则、构建工具和测试实践。这个项目提供了学习和巩固这些技能的平台,同时也为更复杂的系统开发打下...
使用CXF的wsdl2java命令行工具,开发者可以在命令行环境中执行转换,同样可以生成与WSDL文件对应的Java代码。 使用CXF的wsdl2java步骤如下: 1. 安装并配置Apache CXF环境。 2. 打开命令行,定位到CXF的bin目录。 ...