现代操作系统运行一个程序的时候,会为其创建一个进程,例如启动一个IDEA,操作系统就会创建一个IDEA进程
注意:如果使用waitFor() 或者长时间不去读取流,由于部分原生平台只为标准输入输出流提供有限的缓冲区大小,未能及时写入子进程的输入流或读取输出流可能会导致子进程阻塞,甚至死锁。
Runtime runtime = Runtime.getRuntime();
try {
Process exec = runtime.exec(cmdStr);
} catch (IOException e) {
e.printStackTrace();
}
Process p = null;
try{
ProcessBuilder processBuilder = new ProcessBuilder("ipconfig", "/all");
processBuilder.
p = processBuilder.start(); //执行ipconfig/all命令
}catch(IOException e){
e.printStackTrace();
}
Java 注释中是这样介绍的:
每个Java应用程序都有一个类运行时实例,它允许应用程序与运行应用程序的环境交互。可以从getRuntime方法获取当前运行时。
常用方法介绍
Runtime runtime = Runtime.getRuntime();
//可用处理器数
int processors = runtime.availableProcessors();
//返回jvm中空闲的内存量 单位字节
long freeMemory = runtime.freeMemory();
System.out.println(freeMemory);
//jvm可使用的最大内存
long maxMemory = runtime.maxMemory();
//jvm总内存
long totalMemory = runtime.totalMemory();
try {
//执行字符串命令
runtime.exec("notepad");
} catch (IOException e) {
e.printStackTrace();
}
// jvm关闭时的钩子(就是在jvm关闭的时候 会启动addShutdownHook方法添加的线程)
runtime.addShutdownHook(new Thread(() -> {
System.out.println("jvm退出");
}));
//通知jvm垃圾回收 但只是通知
runtime.gc();
long nowFreeMemory = runtime.freeMemory();
System.out.println(nowFreeMemory);
runtime.exit(1);
//exit 下面语句不会执行 包括finally{}
System.out.println("processors=" + processors + ", freeMemory=" + freeMemory + ", maxMemory=" + maxMemory + ", totalMemory=" + totalMemory);
应用程序无法创建自己的此类实例。
不想敲了看,这篇文章总结的可以
注意 使用processBuilder.command(cmds) 每个命令不要包含空格,以免发生意外
如下:
ArrayList cmds = new ArrayList<>();
cmds.add("curl");
cmds.add("-X");
cmds.add("POST");
因为我们与不同的进程交互,每个进程像我们返回的字符集编码是不确定的
所以用一些较大的字符集来接收,因为他们可以兼容一些字符集,这里不做过多描述,有兴趣的可以看这篇文章
Java中的乱码
可以使用GBK或者UTF-8来接收解决中文乱码的问题
但是如果外部进程是用UTF-8编码但是我们用GBK接收 ,在GBK中 一个中文2字节,UTF-8是3字节,所有肯定乱码
//UTF-8编码但是我们用GBK接收
//cannot connect to 127.0.0.1:5555: 由于目标计算机积极拒绝,无法连接。 (10061)
String s = "cannot connect to 127.0.0.1:5555: 鐢变簬鐩\uE1BD爣璁$畻鏈虹Н鏋佹嫆缁濓紝鏃犳硶杩炴帴銆� (10061)";
byte[] gbks = s.getBytes("GBK");
//GBK转UTF-8
System.out.println(new String(gbks, StandardCharsets.UTF_8));
输出
cannot connect to 127.0.0.1:5555: 由于目标计算机积极拒绝,无法连接�? (10061)
为什么。变成了�? 因为GBK中文2字节,UTF-8中文3字节,在用GBK接收的时候如果字节数不是偶数那么最后一个字节GBK识别不出来,就会用半角Ascii字符的 “?” 代替,所以数据就被破坏,所以接收采用单字节的ISO-8859-1数据就不会被破坏关于GBK和UTF-8互转乱码的可以看这篇文章介绍的很不错
总结
1.采用ISO-8859-1接收
2.判断是否是utf-8
public static String getUtf8String(String str) {
if (str != null && str.length() > 0) {
try {
byte[] bytes = str.getBytes(StandardCharsets.ISO_8859_1);
String encode = "";
boolean pdUtf = false;
pdUtf = validUtf8(bytes);
if (pdUtf) {
encode = String.valueOf(StandardCharsets.UTF_8);
} else {
encode = "GBK";
}
str = new String(str.getBytes(StandardCharsets.ISO_8859_1), encode);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return str;
}
public static boolean validUtf8(byte[] data) {
int i = 0;
int count = 0;
while (i < data.length) {
int v = data[i];
if (count == 0) {
if ((v & 240) == 240 && (v & 248) == 240) {
count = 3;
} else if (((v & 224) == 224) && (v & 240) == 224) {
count = 2;
} else if ((v & 192) == 192 && (v & 224) == 192) {
count = 1;
} else if ((v | 127) == 127) {
count = 0;
} else {
return false;
}
} else {
if ((v & 128) == 128 && (v & 192) == 128) {
count--;
} else {
return false;
}
}
i++;
}
return count == 0;
}
cmd /c 是执行完命令后关闭命令窗口。
cmd /k 是执行完命令后不关闭命令窗口。
cmd /c start 会打开一个新窗口后执行指令,原窗口会关闭。
cmd /k start 会打开一个新窗口后执行指令,原窗口不会关闭。
/**
* cmd /c 是执行完命令后关闭命令窗口
*/
private static final String CLOSE_AFTER_EXECUTION = "cmd /c ";
/**
* 是执行完命令后不关闭命令窗口
*/
private static final String DO_NOT_CLOSE_AFTER_EXECUTION = "cmd /k ";
/**
* 会打开一个新窗口后执行命令,原窗口会关闭
*/
private static final String OPEN_NEW_WINDOWS_EXECUTION_OLD_WINDOWS_CLOSE = "cmd /c start";
/**
* 会打开一个新窗口后执行命令,原窗口不会关闭
*/
private static final String OPEN_NEW_WINDOWS_EXECUTION_OLD_WINDOWS_NOT_CLOSE = "cmd /k start";
private static final String CD = "cd ";
public static final String WRAP = System.getProperty("line.separator");
/**
* cmd 输入流
*/
public static BufferedReader bufferedReader;
/**
* cmd 输出流
*/
private static BufferedWriter bufferedWriter;
/**
* 执行完命令后不关闭命令窗口的进程
*/
private static Process exec = null;
private static Thread readThread;
private static AtomicBoolean first = new AtomicBoolean(true);
private static volatile String currentlyExecutedCommand;
/**
* 执行完命令后关闭命令窗口
*
* @param cmdStrBuf 命令
* @return
*/
public static String closeAfterExecution(StringBuffer cmdStrBuf) {
cmdStrBuf.insert(0, CLOSE_AFTER_EXECUTION);
return executeCmd(cmdStrBuf.toString());
}
/**
* 执行完命令后不关闭命令窗口
*
* @param cmdStrBuf 命令
* @return
*/
public static void notCloseAfterExecution(StringBuffer cmdStrBuf) {
cmdStrBuf.insert(0, DO_NOT_CLOSE_AFTER_EXECUTION);
appendCmd(cmdStrBuf.toString());
}
public static void notCloseAfterExecution(String cmdStr) {
StringBuffer cmdStrBuf = new StringBuffer(cmdStr);
cmdStrBuf.insert(0, DO_NOT_CLOSE_AFTER_EXECUTION);
appendCmd(cmdStrBuf.toString());
}
/* public static String openNewWindowsExecutionOldWindowsClose(StringBuffer cmdStrBuf) {
cmdStrBuf.insert(0, OPEN_NEW_WINDOWS_EXECUTION_OLD_WINDOWS_NOT_CLOSE);
return executeCmd(cmdStrBuf.toString());
}*/
public static void cdPath(String path) {
StringBuffer stringBuffer = new StringBuffer(CD);
stringBuffer.append(path);
notCloseAfterExecution(stringBuffer);
}
public static void main(String[] args) throws Exception {
/* String ss = "cannot connect to 127.0.0.1:5555: 由于目标计算机积极拒绝,无法连接。 (10061)";
byte[] bytes = ss.getBytes(StandardCharsets.UTF_8);
String s = "cannot connect to 127.0.0.1:5555: 鐢变簬鐩\uE1BD爣璁$畻鏈虹Н鏋佹嫆缁濓紝鏃犳硶杩炴帴銆� (10061)";
byte[] gbks = s.getBytes("GBK");
Charset gbk = Charset.forName("GBK");
ByteBuffer encode = gbk.encode(s);
Charset utf = Charset.forName("UTF-8");
CharBuffer decode = utf.decode(encode);
for (int i = 0; i < decode.length(); i++) {
System.out.print(decode.get(i));
}
System.out.println(encode.toString());
System.out.println(new String(bytes, "GBK"));
System.out.println(new String(new String(gbks, StandardCharsets.ISO_8859_1).getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8));
System.out.println(new String(gbks, StandardCharsets.UTF_8));*/
}
private static Object outputObject;
private static String methodName;
public static void setOutputAddress(Object obj, String methodName) {
CmdUtil.methodName = methodName;
CmdUtil.outputObject = obj;
}
public static String getUtf8String(String str) {
if (str != null && str.length() > 0) {
try {
byte[] bytes = str.getBytes(StandardCharsets.ISO_8859_1);
String encode = "";
boolean pdUtf = false;
pdUtf = validUtf8(bytes);
if (pdUtf) {
encode = String.valueOf(StandardCharsets.UTF_8);
} else {
encode = "GBK";
}
str = new String(str.getBytes(StandardCharsets.ISO_8859_1), encode);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return str;
}
public static boolean validUtf8(byte[] data) {
int i = 0;
int count = 0;
while (i < data.length) {
int v = data[i];
if (count == 0) {
if ((v & 240) == 240 && (v & 248) == 240) {
count = 3;
} else if (((v & 224) == 224) && (v & 240) == 224) {
count = 2;
} else if ((v & 192) == 192 && (v & 224) == 192) {
count = 1;
} else if ((v | 127) == 127) {
count = 0;
} else {
return false;
}
} else {
if ((v & 128) == 128 && (v & 192) == 128) {
count--;
} else {
return false;
}
}
i++;
}
return count == 0;
}
/**
* 输出目的地
*
* @param String 输出内容
*/
private static void outputDestination(String content) {
if (outputObject == null) {
throw new NullPointerException("outputObject is null");
}
if (methodName == null) {
throw new NullPointerException("methodName is null");
}
Class<?> aClass = outputObject.getClass();
Method method = null;
try {
method = aClass.getMethod(methodName, String.class);
method.invoke(outputObject, CmdUtil.getUtf8String(content));
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
private static void processOutput(String cmdStr) {
first.set(true);
System.out.println("out");
currentlyExecutedCommand = cmdStr;
if (readThread == null) {
readThread = new Thread(() -> {
BufferedReader bufferedReader = CmdUtil.bufferedReader;
try {
String text = bufferedReader.readLine();
while (text != null) {
if (text.equals("")) {
text = bufferedReader.readLine();
continue;
}
StringBuilder outStr = new StringBuilder();
if (first.get()) {
outStr.append(CmdUtil.WRAP).append(new Date()).append("--->").append(currentlyExecutedCommand).append(text).append(CmdUtil.WRAP);
first.set(false);
} else {
outStr.append(text).append(CmdUtil.WRAP);
}
outputDestination(outStr.toString());
text = bufferedReader.readLine();
}
} catch (IOException e) {
e.printStackTrace();
}
}, "readThread");
readThread.start();
}
}
private static void appendCmd(String cmdStr) {
if (!cmdStr.endsWith(WRAP)) {
cmdStr = cmdStr + WRAP;
}
if (Objects.isNull(exec)) {
Runtime runtime = Runtime.getRuntime();
try {
exec = runtime.exec(cmdStr);
if (bufferedWriter == null) {
bufferedWriter = new BufferedWriter(new OutputStreamWriter(exec.getOutputStream(), "GBK"));
}
if (bufferedReader == null) {
SequenceInputStream sis = new SequenceInputStream(exec.getInputStream(), exec.getErrorStream());
bufferedReader = new BufferedReader(new InputStreamReader(sis, StandardCharsets.ISO_8859_1));
}
} catch (IOException e) {
e.printStackTrace();
}
} else {
try {
bufferedWriter.write(cmdStr);
bufferedWriter.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
processOutput(cmdStr);
}
}