`

Java 命令行工具

    博客分类:
  • Java
阅读更多

我使用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]-->

 

 

 

 

 

 

swingworkdone()方法还没有完全执行完毕,就执行proc.waitFor()后面的语句

使用swingwork 可以在界面上异步的看到执行结果,而不是等待执行完之后才一次性打印出来,影响用户体验。这就是swingwork存在的目的。

解决方法:

Process进行封装,看下面标黄的代码,若looptrue则会死循环,一直等待。

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();

       

    }

}

 

 

那么时候终止循环呢?

swingworkdone()方法中:

@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

 

 

 

  • 大小: 37.5 KB
  • 大小: 78.3 KB
  • 大小: 84.8 KB
  • 大小: 28.8 KB
2
2
分享到:
评论

相关推荐

    java命令行辅助工具

    Java命令行辅助工具是一款专为Java开发者设计的小型应用程序,旨在简化Java源代码的编译和执行过程。在日常开发中,我们通常需要通过命令行界面(CLI)来操作Java程序,这包括编译`.java`源文件为`.class`字节码文件...

    Java 命令行以及Java工具总结

    下面将对这些Java命令行工具进行详细的总结和说明。 一、基础工具(Basic Tools) 1. javac:Java编程语言的编译器。开发者使用它将.java源文件编译成.class字节码文件,以便能够在JVM上运行。 2. java:Java应用...

    精品软件工具--圣天诺软锁的Java命令行工具:验证授权、获取授权信息、获取机器指纹信息、更新授权文件等.zip

    精品软件工具--圣天诺软锁的Java命令行工具:验证授权、获取授权信息、获取机器指纹信息、更新授权文件等

    基于Java语言实现的命令行工具-everything.zip

    在创建命令行工具时,Java提供了丰富的类库,如`java.util.Scanner`用于用户输入处理,`java.io`包下的类用于文件操作,`java.lang.ProcessBuilder`可以调用系统命令,以及`java.nio`非阻塞I/O流等,这些都使得Java...

    Java cmd命令行模拟工具

    Java cmd命令行模拟工具是一种用于在Java环境中模拟操作系统命令行工具的实用程序。它使得开发者能够在Java代码中执行系统命令,获取命令输出,并对命令行交互进行控制,这对于自动化测试、脚本编写以及需要与系统...

    Java命令行classpath的设置

    Java命令行classpath(类路径)的设置是Java开发过程中的一项基础操作,对于理解和运行Java程序至关重要。类路径是指定Java虚拟机(JVM)在执行Java程序时查找类文件的位置。正确配置类路径能确保JVM能够找到并加载...

    rythm-util:这是一个简单的Java命令行工具,其中包装了RythmTemplateEngine

    这是包装RythmTemplateEngine的简单Java命令行工具: 用法java -jar rythm-util [json string] rythm-util将[json字符串]解析为一个哈希映射,该映射映射在zhy2002.rythm.RythmContext对象中。 RythmContext为对象...

    java命令参数大全(pdf版)

    这份PDF文档详细列举并解释了Java命令行接口(JVM)的各种参数,旨在帮助开发者更好地理解和使用Java命令行工具。 Java命令通常以`java`或者`javac`为起点,其中`java`用于执行已编译的Java类文件,而`javac`则是...

    eclipse java 命令行参数

    这篇博客文章将探讨如何在Eclipse中配置和使用Java命令行参数,这对于理解程序的运行行为以及调试是非常有帮助的。 在Java程序中,命令行参数是通过`main`方法的`String[] args`数组传递的,它们允许我们在不修改...

    java命令行文件管理器

    Java命令行文件管理器是一款基于Java编程语言开发的实用工具,专为用户在终端环境中提供高效、便捷的文件操作体验。这款程序集成了多种文件管理功能,如创建、删除、重命名、拷贝文件,浏览目录,以及压缩与解压缩、...

    depchecker:用于检查 maven 最新版本的 build.gradle 依赖项的 Java 命令行工具

    调试器用于检查 maven 最新版本的 build.gradle 依赖项的 Java 命令行工具用法: ./java -jar depchecker-all-1.0.jar 构建可运行的 jar: ./gradlew fatJarJar 将位于 build/libs 注意:您必须使用 java 8 来构建...

    CSV For Java命令行工具-开源

    CSV for Java是一个专为Java设计的开源库,它提供了方便的API以及命令行工具,使得开发者在处理CSV文件时能更加高效和灵活。 该库的核心功能包括: 1. **读取CSV文件**:CSV for Java提供了一套完整的API,允许...

    JDK14-installation-guide.pdf

    本指南涵盖了JDK14的安装、配置、环境变量设置、Java命令行工具使用等方面的知识点。 安装JDK14 JDK14的安装分为两种方式:在线安装和离线安装。在线安装需要连接互联网,通过 Oracle 官方网站下载并安装JDK14。...

    fritzcontrol:一个用于管理AVM炸弹盒父母控件的Java命令行工具

    一个用于管理AVM炸弹盒父母控件的Java命令行工具 用法: java -jar &lt;jar&gt; -u &lt;username&gt; -p &lt;password&gt; -D &lt;Device&gt; -P 其他选项: -url默认为fritz.box -auth可能的选项是MD5 (默认)和PBKDF2 (新的炸弹盒)

    Java的命令行进度条 JCmdLineProgess

    使用JCmdLineProgress库,开发者可以方便地在Java命令行程序中集成进度条,提高用户体验。通过实例化库提供的类,设置参数,然后在执行任务时调用相应的更新方法,就可以实现动态的进度显示。 例如,以下是一个简单...

    java中命令行下的小命令

    ### Java中的命令行工具 在Java开发过程中,虽然现代IDE(如IntelliJ IDEA、Eclipse等)提供了非常丰富的功能,使得很多开发工作变得更加便捷,但掌握一些基本...希望本文能够帮助你更好地理解和使用Java命令行工具。

    Android-Java微信支付APIv3平台证书的命令行下载工具

    本文将详细讲解如何使用Java命令行工具下载微信支付API v3的平台证书。 微信支付API v3的平台证书是一个PEM格式的文件,包含了商户的私钥和公钥信息。在进行微信支付接口调用时,需要使用该证书来签名和验签,确保...

    Java 命令行应用开发

    总的来说,"Java命令行应用开发"涵盖了Java编程的多个方面,包括语言基础、输入/输出、异常处理、文件操作、设计原则、构建工具和测试实践。这个项目提供了学习和巩固这些技能的平台,同时也为更复杂的系统开发打下...

    把wsdl文件或地址转化成java代码工具

    使用CXF的wsdl2java命令行工具,开发者可以在命令行环境中执行转换,同样可以生成与WSDL文件对应的Java代码。 使用CXF的wsdl2java步骤如下: 1. 安装并配置Apache CXF环境。 2. 打开命令行,定位到CXF的bin目录。 ...

Global site tag (gtag.js) - Google Analytics