IO输入输出

介绍

IO 实际就是输入流IN 输出 OUT 输出流分stderr(标准错误输出) 和stdout(标准输出),c语言里 对应的就是全局对象stdin stdout stderr java里对应的就是System.in System.out System.err。 操作系统启动程序的时候我们可以指定程序的输入流和输出流以及错误流指向哪里。

System.err和System.out

标准错误输出流和标准输出流是有区别的。输出流是有缓存的只有遇到换行符或者结束的时候才会输出,而err是直接输出的。

shell或者cmd里的重定向

> 重定向输出流 2> 重定向错误输出流 < 重定向输入流

echo 1 > 1.txt
echo < 1.txt 

java子进程

通过Runtime.exec会产生一个子进程。子进程的输入流 对应的就是父进程的输出流 子进程的输入流 对于父进程就是输出流。

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实际就是指向子进程的标准输出流 process.getErrorStream实际就是指向子进程的标准错误输出流 process.getOutputStream实际就是子进程的输入流

由于计算机默认编码是gbk所以 获取ping的标准输出指向了gbk的Reader 读取每一行的ping输出 打印到我们程序的输出 完成了最简单的ping功能

IO就像插座 我们把任意的IO对接起来

把cmd的IO和java的IO对接起来

/**
 *  对接java的输出流到cmd的输入流
 *  必须调用
 *  最近\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();
    }
}

/**
 *  对接cmd的输入流到java的输出流
 */
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 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对接到socket的IO上 那么就可以实现远程访问cmd

socketIO和cmdIO对接

启动Server之后再启动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();
    }
}