JAVA标准I/0详解

来源:互联网 发布:好玩不费钱的游戏知乎 编辑:程序博客网 时间:2024/06/05 05:11

     在JAVA的类库java.lang中我们经常用到System类的System.in,,System.out这种控制台输入输出,这就是所谓的标准流。本文试着对标准I/0做一个比较详细的说明。

标准I/0源码

      JAVA里面提供了3中标准I/0模型,即System.in,System.out,System.err。我们先看看这几种模型的源码:

      

public final static InputStream in = nullInputStream();  public final static PrintStream out = nullPrintStream();  public final static PrintStream err = nullPrintStream();  
      他们都是静态属性的字段,因此能直接用System类直接调用,这些字段实际上private static void initializeSystemClass()中初始化的:

private static void initializeSystemClass() {        FileInputStream fdIn = new FileInputStream(FileDescriptor.in);      FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);      FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);      setIn0(new BufferedInputStream(fdIn));      setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true));      setErr0(new PrintStream(new BufferedOutputStream(fdErr, 128), true));    }  

    FileDescriptor.out,FileDescriptor.in和FileDescriptor.err其实是 

public static final FileDescriptor in = standardStream(0);  public static final FileDescriptor out = standardStream(1);  public static final FileDescriptor err = standardStream(2);  

     明显可以看出它们都是标准流,即常见的控制台输入输出,这也是系统默认的输入输出。接下来看看它们的用法与区别。

标准I/0的使用

     System.in的使用

         (1)从System.in.read()说起

                 为什么从这说起呢?因为字段System.in事实上是InputStream类,我们自然想到Inputstream类里面有什么读取的方法。可以看到有两个,一个是read(),另外一个是read(byte [])。我们经常使用的int in=System.in.read()就表示的“从控制台读取一个字节的内容,并且把它的ASCII码作为返回值”。因此,写这句代码以后我们无论是控制台输入abc还是只输入a,变量in得到的值都会是97。接着看看另外一个read(byte []),看看API文档,它的含义是:从控制台读取一个字节数组,并且返回读取的字节数组的数量。具体的看看下面的例子就明白了,在main函数里面放上下面这段代码,然后从控制台敲入一串字符,看看结果。

byte[] b = new byte[1024];          int count = System.in.read(b);          System.out.println(new String(b, 0, count)); 

               可以说如果单纯的直接对System.in操作来接受控制台的输入,我们能做到的太少,因此我们要接受控制台的输入我们需要对它进行包装,其中一种包装方式就是用其他的方式进行包装,由于装饰流DataInputStream能够操作基本数据类型,而且他的构造方法是DataInputStream(InputStream in)。那我们里所当然的认为这样操作:

DataInputStream stdin=new DataInputStream((System.in));

              然后调用其中的方法来读取基本数据类型就可以,但是很遗憾,这么不会得到理想的结果,本人并没有想明白其中的原因,还请大神看了这篇文章以后做一个解释。另外值得一说的是,类InputStreamReader类是连接字节流和字符流的桥梁,我们可以通过这个类用缓冲字符流对System.in进行包装,如下:

 BufferedReader buf=new BufferedReader(new InputStreamReader(System.in)); String s=buf.readLine(); System.out.println(s);

               这么的还是能得到理想的结果的。那么我们到底怎么从控制台读取各种基本数据类型呢?这就是初学者一上手用到的Scanner类。

         (2)用Scanner包装System.in

                通过import类java.util.Scanner我们就可以使用这个类,这个类有一个构造方法Scanner(InputSteam in),并且这个类里面有操作各种数据类型的方法。因此我们可以将其包装成一个Scanner类引用,然后调用方法来从控制台读取基本数据。如下:

Scanner in=new Scanner(System.in);int tt=in.nextInt();System.out.println(tt);

                这段代码大家再熟悉不过了吧,就不多说了,对System.in相信已经很熟悉了,下面再说说另外两种标准I/O。

    System.out和System.err的使用

         这两个都是控制台输出。从源码可以看到,他们都是PrintStream类字段,是已经包装过的,我们可以调用方法println等对他们进行输出,那么它们有什么区别呢?先看看这段代码:

import java.lang.*;import java.util.*;import java.io.*;public class fanxing{public static void main(String []args){System.out.println("hello world");System.err.println("hello world");}}
        运行结果如下:


        

           看到差异了吧,这是因为out是正常输出,而err是错误输出,错误的应该具有警示作用,因此用err输出的内容是错误的字体。下面说说他们的差别。系统既然可以默认,程序就能修改,也就是从定向。就是说通过设置,让System.out把信息输出到你想要的地方,比如文件,也就成了日志文件。一般的信息和错误信息是不同的,那必须得分开。比如你可以把一般的信息和错误信息打印到不同的文件里面,你就可以很快找到错误信息,而不至于被淹没在大量的一般信息里面。这就是为什么你的系统日志分一般日志和错误日志。 还有一个区别是,out是缓存输出的,err是不缓存的,因为它紧急。接下来说说重定向。

重定向

     标准I/O默认的是控制台输入输出,那么我们可以将他们修改,这就是重定向,对于重定向System有3种方法,分别是setIn(InputStream),setOut(PintStream),setErr(PrintStream)。我们可以将他们重定向到文件里,这就实现了我们常见的日志系统,如下代码:

package jdk.lang;    import java.io.BufferedInputStream;  import java.io.File;  import java.io.FileInputStream;  import java.io.FileNotFoundException;  import java.io.FileOutputStream;  import java.io.IOException;  import java.io.InputStream;  import java.io.PrintStream;    public class SystemIOE {      public static void main(String[] args) throws Exception {          redirect();          helloIO();      }        private static void helloIO() throws IOException {          System.out.println("Hello Out");          System.err.println("Hello Error");          byte[] b = new byte[1024];          int count = System.in.read(b);          System.out.println(new String(b, 0, count));      }        public static void redirect() throws FileNotFoundException {          InputStream in = new BufferedInputStream(new FileInputStream(new File(                  "c:/in.txt")));          System.setIn(in);          PrintStream out = new PrintStream(new FileOutputStream(new File(                  "c:/out.log")));          System.setOut(out);          PrintStream err = new PrintStream(new FileOutputStream(new File(                  "c:/err.log")));          System.setErr(err);      }  }  

      关于JAVA的标准I/O就说这么多吧。


      参考文章:Java System 类详解 - in, out, errhttp://jackycheng2007.iteye.com/blog/1473625

     



0 0
原创粉丝点击