JAVA标准I/0详解

本文详细介绍了JAVA中的标准输入输出System.in、System.out和System.err,包括它们的源码、使用方法以及如何使用Scanner包装System.in。此外,还讲解了System.out与System.err的区别,特别是System.err用于错误输出的特性。最后,讨论了重定向概念,通过System类的setIn、setOut和setErr方法实现输入输出到文件,以构建日志系统。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     在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

     



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值