有很多的时候需要使用命令行去做一些操作,简单的调用命令行或者bat批处理文件不一定能满足要求;由于公司里边要手动去刷公司应用包到安卓目标设备上去,再重启安装,全部都要手动敲命令行,甚是繁琐,故本人制作了一个Java调用命令行的工具。
还有很多可以改进的地方,如可以定义单个命令的超时时间,单个命令的返回解析等等。如果读者有需要,可以自行更改。
转载请注明出处!
下面贴代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
public class CmdProcessor {
private Process mProcess; // the cmd process
private PrintWriter mWriter; // write cmd streams to process
private BufferedReader mReader; // log the cmd response
private volatile boolean mStop; // stop the process
private LinkedBlockingDeque<String> mCmds; // the cmd container
private boolean mLoggable = true; // print log
private boolean mWarnTimeout = false;
private long mTimeoutMillis = 30 * 1000; // 30s
protected long mCmdStartMillis; // record the cmd start time
protected long mProStartMillis; // record the process start time
public CmdProcessor() {
this(null);
}
public CmdProcessor(Collection<String> cmds) {
mCmds = new LinkedBlockingDeque<String>();
if (cmds != null) {
mCmds.addAll(cmds); // here is your cmds
}
}
private void init() throws IOException {
mProcess = Runtime.getRuntime().exec("cmd", getEnvs());
mReader = new BufferedReader(new InputStreamReader(mProcess.getInputStream()));
mWriter = new PrintWriter(new OutputStreamWriter(mProcess.getOutputStream()));
mCmdStartMillis = System.currentTimeMillis();
mProStartMillis = mCmdStartMillis;
if (mWarnTimeout) {
warnTimeout();
}
}
private String[] getEnvs() {
LinkedList<String> envList = new LinkedList<String>();
Map<String, String> envMap = System.getenv();
for (Entry<String, String> env : envMap.entrySet()) {
if (!env.getKey().contains("=") && !env.getValue().contains("=")) {
envList.add(env.getKey() + "=" + env.getValue());
}
}
String[] evns = new String[envList.size()];
return envList.toArray(evns);
}
public void addFirst(String cmd) {
mCmds.addFirst(cmd);
}
public void addLast(String cmd) {
mCmds.addLast(cmd);
}
public void add(String cmd) {
addLast(cmd);
}
/**
* Print warning if cmd has no response, you can disable it
*/
private void warnTimeout() {
new Thread(new Runnable() {
@Override
public void run() {
while (!mStop) {
long passedSec = (System.currentTimeMillis() - mCmdStartMillis);
if (passedSec > mTimeoutMillis) {
System.out.println("[" + mCmds.peek() + "] cost seconds:" + passedSec / 1000);
}
try {
Thread.sleep(1050);
} catch (InterruptedException e) {
}
}
}
}).start();
}
public void setLoggable(boolean loggable) {
mLoggable = loggable;
}
public void waitFor() throws InterruptedException, IOException {
mProcess.waitFor();
stop();
}
public void waitFor(final long timeout, TimeUnit timeUnit) throws Exception {
String versionStr = System.getProperty("java.version");
float version = Float.valueOf(versionStr.substring(0, 3));
if (version >= 1.8f) {
mProcess.waitFor(timeout, timeUnit);
} else {
mockupWaitFor(timeout, timeUnit);
}
stop();
}
/**
* If JDK level is lower than 1.8, you can't use method
* Process.waitFor(long, TimeUnit). So here mock up a waitFor(long,
* TimeUnit) method.
*
* @param timeout
* @throws Exception
*/
private void mockupWaitFor(long timeout, TimeUnit timeUnit) throws Exception {
final long timeMillis = timeUnit.toMillis(timeout);
final Object tmpLock = new Object();
new Thread(new Runnable() {
@Override
public void run() {
long start = System.currentTimeMillis();
while (true) {
if (System.currentTimeMillis() - start > timeMillis) {
synchronized (tmpLock) {
tmpLock.notify();
}
break;
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
synchronized (tmpLock) {
tmpLock.wait();
}
}
private void executeCmd(String cmd) {
if (!mStop) {
mWriter.println(cmd);
mWriter.flush();
mCmdStartMillis = System.currentTimeMillis();
}
}
public void start() throws Exception {
init();
System.out.println();
new Thread(new Runnable() {
@Override
public void run() {
try {
processCmds();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
public void stop() throws IOException {
mStop = true;
mProcess.destroy();
mReader.close();
mWriter.close();
}
public boolean isStopped() {
return mStop;
}
private void processCmds() throws Exception {
boolean firstReply = true;
StringBuffer buffer = new StringBuffer();
char[] chars = new char[1024];
while (!mStop) {
if (mReader.ready()) {
int len = mReader.read(chars);
buffer.append(chars, 0, len);
if (mLoggable) {
System.out.print(new String(chars, 0, len));
}
} else {
String log = buffer.toString();
boolean isReply = isCmdReply(mCmds.peek(), log);
if (isReply) {
buffer.delete(0, buffer.length());
if (firstReply) {
firstReply = false;
} else {
onCmdReply(mCmds.poll(), log); // on cmd reply
}
if (mCmds.peek() == null) { // process next cmd
onFinish();
} else {
String nextCmd = mCmds.peek();
preExecuteCmd(nextCmd);
executeCmd(nextCmd);
}
}
}
}
}
// reply???
protected boolean isCmdReply(String cmd, String log) throws Exception {
String userDir = System.getProperty("user.dir");
return log.contains(userDir);
}
// on cmd reply
protected void onCmdReply(String cmd, String reply) throws Exception {
}
// pre-execute cmd
protected void preExecuteCmd(String cmd) throws Exception {
}
// all the cmds has been executed
protected void onFinish() throws Exception {
stop();
if (mLoggable) {
long costSec = (System.currentTimeMillis() - mProStartMillis) / 1000;
System.out.println("\nCost time: " + costSec);
}
}
public static void main(String[] args) throws Exception {
CmdProcessor pro = new CmdProcessor();
pro.addFirst("dir");
pro.start();
List<String> cmds = new LinkedList<>();
cmds.add("dir /a");
CmdProcessor cd = new CmdProcessor(cmds);
cd.start();
}
}