欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java 命令行工具

程序员文章站 2022-05-18 12:30:03
...

我使用JAVA swing做了一个命令行工具:
Java 命令行工具
            
    
    博客分类: Java SwingWorker并行并发执行本地命令cmd 
 使用的核心技术是SwingWorker,运行效果:


Java 命令行工具
            
    
    博客分类: Java SwingWorker并行并发执行本地命令cmd 
 
Java 命令行工具
            
    
    博客分类: Java SwingWorker并行并发执行本地命令cmd 
 核心工具类:

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 命令行工具
            
    
    博客分类: Java SwingWorker并行并发执行本地命令cmd 
笔记: 

遇到的问题

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

 

 

 

  • Java 命令行工具
            
    
    博客分类: Java SwingWorker并行并发执行本地命令cmd 
  • 大小: 37.5 KB
  • Java 命令行工具
            
    
    博客分类: Java SwingWorker并行并发执行本地命令cmd 
  • 大小: 78.3 KB
  • Java 命令行工具
            
    
    博客分类: Java SwingWorker并行并发执行本地命令cmd 
  • 大小: 84.8 KB
  • Java 命令行工具
            
    
    博客分类: Java SwingWorker并行并发执行本地命令cmd 
  • 大小: 28.8 KB