介紹
IO 實(shí)際就是輸入流IN 輸出 OUT
輸出流分stderr(標(biāo)準(zhǔn)錯(cuò)誤輸出) 和stdout(標(biāo)準(zhǔn)輸出),c語言里 對(duì)應(yīng)的就是全局對(duì)象stdin stdout stderr
java里對(duì)應(yīng)的就是System.in System.out System.err。
操作系統(tǒng)啟動(dòng)程序的時(shí)候我們可以指定程序的輸入流和輸出流以及錯(cuò)誤流指向哪里。
System.err和System.out
標(biāo)準(zhǔn)錯(cuò)誤輸出流和標(biāo)準(zhǔn)輸出流是有區(qū)別的。輸出流是有緩沖的,只有遇到換行符或者結(jié)束的時(shí)候才會(huì)輸出,而err是直接輸出的。
shell或者cmd里的重定向
> 重定向輸出流
2> 重定向錯(cuò)誤輸出流
< 重定向輸入流
echo 1 > 1.txt
echo < 1.txt
java子進(jìn)程
通過Runtime.exec會(huì)產(chǎn)生一個(gè)子進(jìn)程。子進(jìn)程的輸入流 對(duì)應(yīng)的就是父進(jìn)程的輸出流 子進(jìn)程的輸入流 對(duì)于父進(jìn)程就是輸出流。
public static void ping(){
try {
Process process=Runtime.getRuntime().exec("ping www.baidu.com");
InputStream in = process.getInputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(in,"gbk"));
String line=null;
while((line=br.readLine())!=null){
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
process.getInputStream實(shí)際就是指向子進(jìn)程的標(biāo)準(zhǔn)輸出流
process.getErrorStream實(shí)際就是指向子進(jìn)程的標(biāo)準(zhǔn)錯(cuò)誤輸出流
process.getOutputStream實(shí)際就是子進(jìn)程的輸入流
由于計(jì)算機(jī)默認(rèn)編碼是gbk所以 獲取ping的標(biāo)準(zhǔn)輸出指向了gbk的Reader
讀取每一行的ping輸出 打印到我們程序的輸出 完成了最簡(jiǎn)單的ping功能
IO就像插座 我們把任意的IO對(duì)接起來
把cmd的IO和java的IO對(duì)接起來
/**
* 對(duì)接java的輸出流到cmd的輸入流
* 必須調(diào)用
* 最近\r\n模擬回車
*/
public static void pipe(InputStream in,OutputStream out){
try {
BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(in,"utf8"));
String line="";
while((line=bufferedReader.readLine())!=null){
out.write(line.getBytes("gbk"));
out.write("\r\n".getBytes("gbk"));
out.flush();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 對(duì)接cmd的輸入流到j(luò)ava的輸出流
*/
public static void pipe(InputStream in,String charset,OutputStream out,String outCharset) throws IOException {
InputStreamReader br = new InputStreamReader(in, charset);
char[] chunk=new char[2048];
int len=0;
StringBuilder stringBuilder=new StringBuilder();
while((len=br.read(chunk,0,2048))!=-1){
stringBuilder.append(chunk,0,len);
System.out.write(stringBuilder.toString().getBytes(outCharset));
System.out.flush();
stringBuilder.delete(0,stringBuilder.length());
}
}
/**
* 啟動(dòng)三個(gè)線程 對(duì)接輸入輸出流和錯(cuò)誤輸出流
*/
public static void socket() throws IOException {
Process process=Runtime.getRuntime().exec("cmd");
new Thread(new Runnable() {
@Override
public void run() {
pipe(System.in,process.getOutputStream());
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
try {
pipe(process.getInputStream(),"gbk",System.out,"utf8");
} catch (IOException e) {
e.printStackTrace();
}
pipe(process.getInputStream(),System.out);
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
try {
pipe(process.getErrorStream(),"gbk",System.err,"utf8");
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
同理我們可以把cmd的IO對(duì)接到socket的IO上 那么就可以實(shí)現(xiàn)遠(yuǎn)程訪問cmd
socketIO和cmdIO對(duì)接
啟動(dòng)Server之后再啟動(dòng)Client可以看到可以使用cmd
public class CMDParent {
/**
* Sysytem.in 專用
* @param out
* @param charset
*/
public static void SystemINpipe(OutputStream out,String charset){
try {
BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(System.in,"utf8"));
String line="";
while((line=bufferedReader.readLine())!=null){
out.write(line.getBytes(charset));
out.write("\r\n".getBytes(charset));
out.flush();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void pipe(InputStream in, String charset, OutputStream out, String outCharset) throws IOException {
InputStreamReader br = new InputStreamReader(in, charset);
char[] chunk=new char[2048];
int len=0;
StringBuilder stringBuilder=new StringBuilder();
while((len=br.read(chunk,0,2048))!=-1){
stringBuilder.append(chunk,0,len);
System.out.write(stringBuilder.toString().getBytes(outCharset));
System.out.flush();
stringBuilder.delete(0,stringBuilder.length());
}
}
}
public class CMDServer extends CMDParent{
private Socket client;
public CMDServer(Socket client) {
try {
Process process=Runtime.getRuntime().exec("cmd");
new Thread(new Runnable() {
@Override
public void run() {
try {
pipe(client.getInputStream(),"utf8",process.getOutputStream(),"gbk");
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
try {
pipe(process.getInputStream(),"gbk",client.getOutputStream(),"utf8");
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
try {
pipe(process.getErrorStream(),"gbk",client.getOutputStream(),"utf8");
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String agrs[]) throws IOException {
ServerSocket serverSocket=new ServerSocket(8091);
Socket client;
while((client=serverSocket.accept())!=null){
new CMDServer(client);
}
}
}
public class CMDClient extends CMDParent {
public static void main(String agrs[]) throws IOException {
Socket socket=new Socket("localhost",8091);
new Thread(new Runnable() {
@Override
public void run() {
try {
pipe(socket.getInputStream(),"utf8",System.out,"utf8");
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
try {
SystemINpipe(socket.getOutputStream(),"utf8");
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}