System类对IO的支持

系统输出

  学完了PrintStream PrintWriter之后我们会发现里面方法很熟悉,例如:print() println() 实际上在之前使用的系统输出就利用了IO流模式完成的,在System类中定义有三个操作的常量:

    标准输出(显示器):public static final PrintStream out

    错误输出:public static final PrintStream err

    标准输入(键盘):public static final InputStream in

  原来之前使用的System.out.println()一直都属于IO的操作范畴。

系统输出

  系统输出有两个常量:out err 而且这两个常量所表示的都是PrintStream类的对象,从Java的设计本质上来讲,这样的两种输出有以下的设计目的:out输出的是希望用户可以看见内容,err是希望输出用户不能看见的内容。

  这两种输出在实际的开发之中都没用。

 1 package cn.Tony.demo;
 2 
 3 public class TestDemo{
 4     public static void main(String[] args) throws Exception {
 5         try {
 6             Integer.parseInt("abc");
 7         }catch(Exception e) {
 8             System.err.println(e);
 9             System.out.println(e);
10         }
11         
12     }
13 }

  System.err也只是作为一个保留的属性提供存在。System.out属于PrintStream,属于OutputStream

范例:

 1 package cn.Tony.demo;
 2 
 3 import java.io.OutputStream;
 4 
 5 public class TestDemo{
 6     public static void main(String[] args) throws Exception {
 7         OutputStream out=System.out;
 8         out.write("世界和平".getBytes());
 9     }
10 }

  抽象类不同的子类针对同一方法有不同的实现,用户调用的时候的核心参考的就是OutputStream。

系统输入 in

  System.in对于的类型是InputStream,而这种的输入流指的是由用户通过键盘进行输入(用户输入),java本身并没有这种直接的用户输入处理,如果要想实现这种输入处理必须用java.io的模式完成

范例:利用InputStream

 1 package cn.Tony.demo;
 2 
 3 import java.io.InputStream;
 4 
 5 public class TestDemo{
 6     public static void main(String[] args) throws Exception {
 7         InputStream input=System.in;//为父类实例化
 8         byte data[]=new byte[1024];//开辟一个空间
 9         System.out.println("请输入信息:");
10         int temp=input.read(data);//数据读取到字节数组中
11         System.out.println("【ECHO】输入内容:"+new String(data,0,temp));
12         
13     }
14 }

  现在发现当用户输入数据的时候需要暂停执行,也就是说程序进入到阻塞状态,直到用户输入完成(按下回车),那么才能向下执行,但是以上的程序本身有一个致命的问题,那么核心点就在于:要开辟的字节数组的长度是固定的,输入内容超过了该长度。如果开辟的量超过长度,只能接受部分数据,保存内存流,

 1 package cn.Tony.demo;
 2 
 3 import java.io.ByteArrayOutputStream;
 4 import java.io.InputStream;
 5 
 6 public class TestDemo{
 7     public static void main(String[] args) throws Exception {
 8         InputStream input=System.in;//为父类实例化
 9         ByteArrayOutputStream bos=new ByteArrayOutputStream();
10         byte data[]=new byte[1024];//开辟一个空间
11         System.out.println("请输入信息:");
12         int temp=0;
13         while((temp= input.read(data))!=-1) {
14             //这里面需要由用户自己来处理换行的问题,因为换行不属于文件结束,所有内容不是-1
15             bos.write(data,0,temp);
16             if(temp<data.length) {
17                 break;
18             }
19         }
20         System.out.println("【ECHO】输入内容:"+new String(bos.toByteArray()));
21         bos.close();
22         input.close();
23     }
24 }

  虽然实现了键盘输入数据的功能,不过整体逻辑混乱,也就是说java本身所提供的System.in该操作不好用

 1 package cn.Tony.demo;
 2 import java.io.InputStream;
 3 public class TestDemo{
 4     public static void main(String[] args) throws Exception {
 5         InputStream input=System.in;//为父类实例化
 6         StringBuffer buf=new StringBuffer();
 7         System.out.println("请输入信息:");
 8         int temp=0; 
 9         while((temp= input.read())!=-1) {
10             if(temp=='\n') {
11                 break;
12             }
13             buf.append((char)temp);
14         }
15         System.out.println("【ECHO】输入内容:"+buf);
16         input.close();
17     }
18 }

  通过以上的比较可以感受到System.in的支持度原本不高,对于英文的操作该勉强可以使用,所以要中文,就必须结合内存流来完成,所以复杂度 是很高的,如果开发都这么写,就非常麻烦了

总结:

  如果要想在IO中进行中文的处理,那么最好的做法是将所有输入的数据保存在一起再处理,这样才可以保证出现乱发,

  BufferedReader类属于一个缓冲的输入流,字符流的操作对象,但是必须清楚一点,对于缓冲流在java.io中定义有两类:字节缓冲流(BufferedInputStream),字符缓冲流(BufferedReader)。

  之所以选择BufferedReader类操作是因为在此类中提供的readLine()方法,这个方法可以直接读取一行数据(以回车为换行符)

    读取一行:public String readLine()throws IOException

  但是如果要想去使用BufferedReader类有一个问题需要注意了,来观察一下BufferdReader

范例;利用BufferedReader实现键盘输入

 1 package cn.Tony.demo;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.InputStreamReader;
 5 
 6 public class TestDemo{
 7     public static void main(String[] args) throws Exception {
 8         BufferedReader buf=new BufferedReader(new InputStreamReader(System.in));
 9         System.out.println("请输入信息:");
10         //默认的换行模式是BufferedReader最大缺点,如果不是因为此缺点,该类还好继续使用
11         String str=buf.readLine();//接受输入信息,默认用回车换行
12         System.out.println(str);
13     }
14 } 

  使用以上的形式实现的键盘输入还有一个最大的特点 ,由于接受的数据类型为String,那么也就证明可以使用正则判断。利用String类的各种操作进行处理,还可以变为各种常用的数据类型,

 1 package cn.Tony.demo;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.InputStreamReader;
 5 
 6 public class TestDemo{
 7     public static void main(String[] args) throws Exception {
 8         BufferedReader buf=new BufferedReader(new InputStreamReader(System.in));
 9         System.out.println("请输入信息:");
10         //默认的换行模式是BufferedReader最大缺点,如果不是因为此缺点,该类还好继续使用
11         String str=buf.readLine();//接受输入信息,默认用回车换行
12         if(str.matches("\\d{1,3}")) {
13             System.out.println("【ECHO】输入信息为:"+Integer.parseInt(str));
14         }else {
15             System.out.println("输入的数据有错误");
16         }
17     }
18 } 

  在很多的开发中依然可能会发现有BufferedReader类的身影,但是这个类随着时间的偏移,基本上使用的频率已经很低了。已经被新的类Scanner所取代了,

总结

  BufferedReader类读取数据很方便(readLin)。

Scanner

  打印流解决的是OutputStream缺陷,BufferedRead解决的是InputStream的缺陷,而java.Util.Scanner解决的是BufferedReader类的一个缺陷。

  Scanner是一个专门进行输入流处理的程序类,利用这个类可以方便处理数据类型。同时也可以直接结合正则表达式进行各项处理。在这个类中关注一下:

    判断是否有指定类型的数据:public boolean hasNextXxx()

    取得指定类型的数据:public 数据 nextXxx()

    定义分隔符:public Scanner useDelimiter(Pattern pattern)

    构造方法:public Scanner(InputStream source)

范例:使用Scanner实现数据的输入

 

 1 package cn.Tony.demo;
 2 
 3 import java.util.Scanner;
 4 
 5 public class TestDemo{
 6     public static void main(String[] args) throws Exception {
 7         Scanner scan=new Scanner(System.in);
 8         System.out.println("请输入数据:");
 9         if(scan.hasNext()) {//现在有输入内容,不判断空字符串
10             System.out.println("【ECHO】输入内容为:"+scan.next());
11         }
12         scan.close();
13     }
14 }

 

  使用Scanner输入还可以接收各种数据类型

范例:

 1 package cn.Tony.demo;
 2 
 3 import java.util.Scanner;
 4 
 5 public class TestDemo{
 6     public static void main(String[] args) throws Exception {
 7         Scanner scan=new Scanner(System.in);
 8         System.out.println("请输入数据:");
 9         if(scan.hasNextInt()) {//现在有输入内容,不判断空字符串
10             int age=scan.nextInt();
11             System.out.println("【ECHO】输入内容为:"+age);
12         }else{
13             System.out.println("ERROR:输入不是数字");
14         }
15         scan.close();
16     }
17 } 

  最为重要的文图它可以对接收的数据类型使用正则表达式进行判断。

范例:利用正则进行判断

 1 package cn.Tony.demo;
 2 
 3 import java.util.Scanner;
 4 
 5 public class TestDemo{
 6     public static void main(String[] args) throws Exception {
 7         Scanner scan=new Scanner(System.in);
 8         System.out.println("请输入数据:");
 9         if(scan.hasNext("\\d{4}-\\d{2}-\\d{2}")) {
10             String birthday=scan.next();
11             System.out.println("生日:"+birthday);
12         }else {
13             System.out.println("错误");
14         }
15         scan.close();
16     }
17 } 

  但是以上的操作在开发中不会出现,

  使用Scanner本身能接收的是一个InputStream类的对象,例如:文件输入流。

 1 package cn.Tony.demo;
 2 import java.io.File;
 3 import java.io.FileInputStream;
 4 import java.util.Scanner;
 5 public class TestDemo{
 6     public static void main(String[] args) throws Exception {
 7         Scanner scan=new Scanner(new FileInputStream(new File("D:"+File.separator+"IO"+File.separator+"data.txt")));
 8         scan.useDelimiter(":");
 9         while(scan.hasNext()) {
10             System.out.println(scan.next());
11         }
12         scan.close();
13     }
14 } 

  Scanner实际上完美的替代了BufferedReader,更好的实现了InputStream操作。

总结:

  以后除了二进制的文件拷贝处理之外,那么只要是针对于程序的信息输出都是用打印流。信息输入都使用Scanner

 

posted on 2019-03-16 14:46  朽木zidiao  阅读(198)  评论(0编辑  收藏  举报

导航