`

Java使用Runtime.exec()给Windows命令提示符做了个外壳,真的很山寨!

阅读更多
    昨天发布的文本编辑器Quickpad-1.2我还有很多地方不满意的,比如控制台没有实现键盘输入功能,今天本想解决这个问题,没想到做成了一个山寨版的Windows命令提示符。

MyConsole的效果如下





下面将代码贴出来,以作备忘。

MyConsole.java
package com.jison.MyConsole;

import java.awt.Color;
import java.awt.Font;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

/**
 * 命令提示符的外壳程序
 * @version	MyConsole-1.0
 * @author	jison
 * @email	jisonami@163.com
 * @time	2015-1-30
 */
public class MyConsole {

	/**
	 * MyConsole主窗体
	 */
	private JFrame jf = new JFrame("MyConsole");
	
	/**
	 * MyConsole的终端文本区
	 */
	private JTextArea consoleTextArea = new JTextArea();
	
	/**
	 * 将终端文本区加入到JScrollPane
	 */
	private JScrollPane jScrollPane = new JScrollPane(consoleTextArea);
	
	/**
	 * 设置默认字体为等宽字体
	 */
	private final Font DEFAULT_FONT = new Font(Font.MONOSPACED, Font.PLAIN, 13);
	
	/**
	 * 控制器对象
	 */
	private MyConsoleControl myConsoleControl;
	
	/**
	 * 程序入口
	 * @param args
	 */
	public static void main(String[] args){
		new MyConsole();
	}
	
	public MyConsole(){
		//初始化UI
		this.setMyConsoleUI();
		//创建键盘监听
		this.createKeyListener();
		//获取当前路径
		String nowPath = (new File(".")).getAbsolutePath();
		nowPath = nowPath.substring(0, nowPath.length()-2);
		//设置当前路径
		MyConsoleDto.getMyConsoleDto().setNowPath(nowPath);
		
		//获取终端控制器
		myConsoleControl = new MyConsoleControl();
		
		//读取运行cmd命令的信息
		String[] cmdArray = new String[3];
		cmdArray[0] = "cmd";
		cmdArray[1] = "/c";
		cmdArray[2] = "cmd";
		myConsoleControl.execCmdThread(cmdArray, 300, consoleTextArea);
	}
	
	private void setMyConsoleUI(){
		//设置终端文本区的字体和颜色
		consoleTextArea.setBackground(Color.BLACK);
		consoleTextArea.setForeground(Color.LIGHT_GRAY);
		consoleTextArea.setFont(DEFAULT_FONT);
		consoleTextArea.setCaretColor(Color.LIGHT_GRAY);
		//设置终端文本区自动换行
		consoleTextArea.setLineWrap(true);
		
		//垂直滚动条需要时自动出现
		jScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		
		jf.add(jScrollPane);
		jf.setSize(680, 450);
		FrameUtil.setFrameCenter(jf);
		//设置窗口的默认关闭操作,退出应用程序
		jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		jf.setVisible(true);
	}
	
	/**
	 * 对consoleTextArea创建键盘监听
	 */
	private void createKeyListener(){
		consoleTextArea.addKeyListener(new KeyListener(){
			@Override
			public void keyReleased(KeyEvent e) {
				
				//保护consoleText已打印文本信息不受编辑
				myConsoleControl.protectHasPrintText(consoleTextArea);
					
				if(e.getKeyCode()==KeyEvent.VK_ENTER) {
					//回车键释放时的操作
					//获取已打印的文本
					String hasPrintText = MyConsoleDto.getMyConsoleDto().getStrConsoleText();
					//读取当前文本
					String nowConsoleText = consoleTextArea.getText();
					//执行当前输入的命令
					if(nowConsoleText.length()>hasPrintText.length()){
						//获取当前输入的命令
						String cmdStr = nowConsoleText.substring(hasPrintText.length()).trim();
						
						//给每条命令加入"cmd /c"的前缀
						cmdStr = "cmd /c "+cmdStr;
						//以空格截取输入命令的cmdArray
						String[] cmdArray = cmdStr.split(" ");
						//执行刚刚输入命令
						myConsoleControl.execCmdThread(cmdArray, 30000, consoleTextArea);
					}
				}
			}
			@Override
			public void keyTyped(KeyEvent e) {}
			@Override
			public void keyPressed(KeyEvent e) {}
		});
	}
	

}


MyConsoleControl.java
package com.jison.MyConsole;


import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import javax.swing.JOptionPane;
import javax.swing.JTextArea;
import javax.swing.text.Document;

/**
 * 处理控制台显示的信息
 * @author	jison
 * @email	jisonami@163.com
 * @time	2015-1-30
 */
public class MyConsoleControl {
	
	/**
	 * 对cd等切换目录的特殊命令的处理
	 * @param cmdArray
	 */
	public void execCdChange(String[] cmdArray){
		//获取当前根目录
		String nowRootDir = MyConsoleDto.getMyConsoleDto().getNowRootDir();
		//当前要切换的目录
		File dir = null;
		//对cd命令进行特殊处理
		if(cmdArray[2].equals("cd")){
			//如果命令数组的长度为4,表明cd命令输入了目录
			if(cmdArray.length==4){
				dir = new File(nowRootDir + cmdArray[3]);
			}
		}
		//切换根驱动器命令
		if(cmdArray[2].length()==2 && cmdArray[2].charAt(1)==':'){
			dir = new File(cmdArray[2]);
		}
		//记录当前目录和上一个目录
		if(dir!=null && dir.exists() && dir.isDirectory()){
			//将当前目录记录为上一个目录
			MyConsoleDto.getMyConsoleDto().setPrePath(MyConsoleDto.getMyConsoleDto().getNowPath());
			//将dir记录为当前目录
			MyConsoleDto.getMyConsoleDto().setNowPath(dir.toString());
		}
	}
	
	/**
	 * 保护已打印文本不受编辑
	 */
	public void protectHasPrintText(JTextArea consoleTextArea){
		//获取已打印的文本
		String hasPrintText = MyConsoleDto.getMyConsoleDto().getStrConsoleText();
		//读取当前终端文本
		String nowConsoleText = consoleTextArea.getText();
		//如果当前终端文本的长度小于已打印文本的长度
		if(consoleTextArea.getText().length()<hasPrintText.length()){
			//恢复已打印的文本
			consoleTextArea.setText(hasPrintText);
		}
		//键盘输入的位置不在‘>’字符之后
		if(consoleTextArea.getText().charAt(hasPrintText.length()-1)!='>'){
			//恢复已打印的文本
			consoleTextArea.setText(hasPrintText);
		}
	}
	
	/**
	 * 以追加的方式打印当前目录信息到consoleTextArea
	 */
	public void printDirInfo(JTextArea consoleTextArea){
		String nowPath = MyConsoleDto.getMyConsoleDto().getNowPath();
		consoleTextArea.append(nowPath+">");
		//记录当前consoleTextArea的文本
		MyConsoleDto.getMyConsoleDto().setStrConsoleText(consoleTextArea.getText());
		//将光标移动到最后
		consoleTextArea.setCaretPosition(consoleTextArea.getText().length());
	}
	
	/**
	 * 在限制时间内执行cmdArray命令
	 * @param cmdArray 命令数组
	 * @param time 时间单位为微秒
	 */
	public void execCmdThread(String[] cmdArray, int time, JTextArea consoleTextArea){
		
		//如果输入的命令为exit,则退出整个程序
		if(cmdArray[2].equals("exit")){
			System.exit(0);
		}
		
		//启动新的线程执行一条命令
		Thread cmdThread = new Thread(new Runnable(){
			@Override
			public void run() {
				outputCapture(cmdArray, consoleTextArea);
			}
		});
		cmdThread.start();
		try {
			cmdThread.join(time);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		//对cd等切换目录的特殊命令的处理
		execCdChange(cmdArray);
		
		//插入一个换行符
		if(!cmdArray[2].equals("cmd")){
			consoleTextArea.append("\n");
		}
		//打印当前目录信息
		printDirInfo(consoleTextArea);
	}
	
	/**
	 * 捕捉cmdArray命令的控制台输出
	 * @param cmdArray
	 */
	public void outputCapture(String[] cmdArray, JTextArea consoleTextArea){
		Process process = null;
		try {
			File dir = new File(MyConsoleDto.getMyConsoleDto().getNowPath());
			// 启动命令行指定程序的新进程
			process = Runtime.getRuntime().exec(cmdArray, null, dir);
		}
		catch(IOException e) {
			System.err.println("创建进程时出错...\n" + e);
			System.exit(1);
		}

		// 获得新进程所写入的流
		InputStream[] inStreams = new InputStream[] {process.getInputStream(),
		process.getErrorStream()};
		//将终端信息追加到consoleTextArea
		this.toTextArea(consoleTextArea, inStreams);
		
		try {
			process.waitFor();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 在jTextArea上显示传入的InputStream数组的信息
	 * @param jTextArea	显示信息的文本区域
	 * @param inStreams 传入要显示的InputStream数组的信息
	 */
	public void toTextArea(JTextArea jTextArea, InputStream[] inStreams){
		for(int i = 0; i < inStreams.length; ++i){
			startConsoleReaderThread(jTextArea, inStreams[i]);
		}
	}

	/**
	 * 单独启用一个线程对控制台信息的处理
	 * @param jTextArea
	 * @param inputStream
	 */
	private void startConsoleReaderThread(JTextArea jTextArea,
			InputStream inputStream) {
		final BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
		new Thread(new Runnable() {
			public void run() {
				StringBuffer sb = new StringBuffer();
				try {
					String s;
					Document doc = jTextArea.getDocument();
					while((s = br.readLine()) != null) {
						boolean caretAtEnd = false;
						caretAtEnd = jTextArea.getCaretPosition() == doc.getLength() ?
							true : false;
						sb.setLength(0);
						jTextArea.append(sb.append(s).append('\n').toString());
						if(caretAtEnd)
							jTextArea.setCaretPosition(doc.getLength());
					}
				}
				catch(IOException e) {
					JOptionPane.showMessageDialog(null,
						"从BufferedReader读取错误:" + e);
					System.exit(1);
				}
			}
		}).start();
	}
}


MyConsoleDto.java
package com.jison.MyConsole;

/**
 * 数据传输对象
 * @author	jison
 * @email	jisonami@163.com
 * @time	2015-1-30
 */
public class MyConsoleDto {

	/**
	 * 使用单例模式设计
	 */
	private static MyConsoleDto myConsoleDto;
	
	/**
	 * 保存当前consoleTextArea的所有文本
	 */
	private String strConsoleText;
	
	/**
	 * 记录当前的根目录
	 */
	private String nowRootDir;
	
	/**
	 * 记录当前命令行打开的目录
	 */
	private String nowPath;
	
	/**
	 * 记录前一个目录
	 */
	private String prePath;
	
	/**
	 * 通过静态方法返回唯一实例
	 * @return
	 */
	public static MyConsoleDto getMyConsoleDto(){
		if(myConsoleDto==null){
			myConsoleDto = new MyConsoleDto();
		}
		return myConsoleDto;
	}

	/**
	 * 其余所有值的getter和setter方法
	 */
	public String getStrConsoleText() {
		return strConsoleText;
	}
	public void setStrConsoleText(String strConsoleText) {
		this.strConsoleText = strConsoleText;
	}
	public String getNowPath() {
		return nowPath;
	}
	public void setNowPath(String nowPath) {
		this.nowPath = nowPath;
	}
	public String getPrePath() {
		return prePath;
	}
	public void setPrePath(String prePath) {
		this.prePath = prePath;
	}
	public String getNowRootDir() {
		this.setNowRootDir(this.nowPath.substring(0, 2));
		return nowRootDir;
	}
	public void setNowRootDir(String nowRootDir) {
		this.nowRootDir = nowRootDir;
	}
}


FrameUtil.java
package com.jison.MyConsole;

import java.awt.Dimension;
import java.awt.Toolkit;

import javax.swing.JFrame;

/**
 * 使JFrame窗口居中显示
 * @author	jison
 * @email	jisonami@163.com
 * @time	2015-1-30
 */
public class FrameUtil {
	public static void setFrameCenter(JFrame jf){
		//使窗口居中显示
		Toolkit toolkit = Toolkit.getDefaultToolkit();
		Dimension screen = toolkit.getScreenSize();
		
		//先乘除,后加减,再位移
		int x = (screen.width-jf.getWidth()) >> 1;
		int y = (screen.height-jf.getHeight() >> 1)-16;
		jf.setLocation(x,y);
	}
}


没了,以上就是全部的代码了。
  • 大小: 49.6 KB
0
0
分享到:
评论

相关推荐

    java执行可执行文件,Runtime.exec、ProcessBuilder、commons-exec

    使用`Runtime.exec()` `Runtime.exec()`是最为传统且简单的执行外部程序的方法。它可以启动一个新的进程,并返回一个代表该进程的`Process`对象。但是,这种方法在处理进程的输入/输出流时存在一定的局限性。 **...

    java.lang.Runtime.exec&#40;&#41; Payload知识点详解

    Java.lang.Runtime.exec() 方法是 Java 语言中用于执行操作系统命令的方法,它可以将参数传递给命令,并执行命令以获取结果。但是,在使用该方法时,需要注意一些重要的知识点,以避免出现问题。 命令参数中不能...

    使用runtime实现linux命令行或shell脚本多次调用

    `Runtime.exec(String command)`方法用于执行单个命令,而如果需要执行包含多个命令的shell脚本,可以使用`Runtime.exec(String[] cmdArray)`,其中cmdArray是一个包含命令及其参数的字符串数组。 下面是一个简单的...

    解决runtime.exec&#40;&#41;执行进程block死锁以及为waitFor设置超时

    完美解决runtime.exec&#40;&#41;执行进程block死锁以及为waitFor设置超时 不需要耗cpu的循环判断exitValue==0 开两个进程搞定

    java调用windows命令

    如果遇到无法删除的问题,可以尝试使用`Runtime.exec()`调用`del`命令强制删除文件。 在实际编程中,处理这些细节能够确保Java程序在Windows环境中正确地调用命令行操作。同时,为了提高代码的可维护性和可读性,...

    halcon-17.12.0.0-windows-runtime.exe

    halcon-17.12.0.0-windows-runtime.exe

    【IDEA】windows环境下IDEA java代码Runtime.getRuntime.exec中shell的执行环境的解决方案

    windows环境下IDEA java代码Runtime.getRuntime.exec中shell的执行环境的解决方案前言解决办法后记 前言 在使用IDEA本地开发监控守护线程的后台,我遇上了执行环境不兼容的问题,爆出各种“xxx不是内部或外部命令,...

    System.Runtime.InteropServices.WindowsRuntime 蓝牙相关开发库

    System.Runtime.InteropServices.WindowsRuntime 是.NET Framework和.NET Core中的一个关键组件,它主要负责提供与Windows运行时(WinRT)API的互操作性。在涉及到蓝牙相关的开发时,这个库扮演着重要的角色,允许C#...

    Runtime 执行bat

    在Java编程语言中,`Runtime`类是每个Java应用程序都有的一个实例,它提供了与运行时环境交互的方法。当我们需要在Java程序中执行系统命令,比如运行一个批处理脚本(.bat文件)时,`Runtime`类或者其扩展类`...

    Java控制命令提示符.txt

    根据提供的文件信息,本文将详细解析与“Java控制命令提示符”相关的知识点,包括如何在Java程序中执行操作系统命令、具体实现方式以及可能遇到的问题和解决办法。 ### 一、Java程序调用操作系统命令的基本原理 ...

    Android中软件的静默安装

    1,申请root权限Runtime.getRuntime().exec&#40;"su"&#41;; 2,通过数据输出流DataOutputStream写入pm install命令; 3,最后获取Process进程的返回值int i = process.waitFor();,如果i=0,则表明已获取root权限。

    深入研究java.lang.Runtime类.doc

    java.lang.Runtime 类是 Java 语言中一个非常重要的类,它提供了访问当前 Java 应用程序的 Runtime 环境的能力。每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。 概述: ...

    ArcGIS Runtime SDK for Java 100.12.0

    如果用Maven获取,当配置稍有问题,也不能...如需在生产环境中使用ArcGIS Runtime SDK for Java,请联系ESRI公司获得授权,现在也有国产替代产品GeoScne Runtime SDK for Java,可以联系易智瑞公司获得相关资源和授权。

    NuGet包 Esri.ArcGISRuntime.100.3.0

    Esri.ArcGISRuntime.100.3.0.nupkg Esri.ArcGISRuntime.LocalServices.100.3.0.nupkg Esri.ArcGISRuntime.Hydrography.100.3.0.nupkg Esri.ArcGISRuntime.UWP.100.3.0.nupkg Esri.ArcGISRuntime.Xamarin.Forms.100.3...

    System.Runtime.Serialization.dll

    1. DataContractSerializer:这是.NET Framework 3.0引入的一个高性能的序列化器,主要用于WCF(Windows Communication Foundation)服务。通过定义数据契约(DataContract),我们可以指定哪些字段或属性应该参与...

    Java调用应用程序和Dos中的命令

    下面是一个简单的示例,展示如何使用`Runtime.exec()`来调用DOS命令`ipconfig`: ```java import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; public class ...

    64位 java runtime 1.8.0.zip

    Java Runtime Environment(JRE)是Java程序运行所需的基础组件,它是Oracle公司提供的Java平台标准版(Java SE)的一部分。在本例中,我们讨论的是64位版本的JRE 1.8.0,适用于Windows操作系统。这个版本的JRE包含...

Global site tag (gtag.js) - Google Analytics