Java 命令行工具

我使用JAVA swing做了一个命令行工具:
Java 命令行工具_第1张图片
 使用的核心技术是SwingWorker,运行效果:


Java 命令行工具_第2张图片
 
Java 命令行工具_第3张图片
 核心工具类:

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构建,结构如下:


Java 命令行工具_第4张图片
笔记: 

遇到的问题

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

 

 

 

你可能感兴趣的:(并发,cmd,并行,执行本地命令,SwingWorker)