Java IO 6- BufferedReader,Scanner键盘输入和err,in,out

err/in/out

  和C/C++一样,Java也有 err/in/out 的概念,Java中是由系统类 System类 给出的。

  含义如下:

// 错误输出
public static final PrintStream err = null;

// 标准输入(键盘)
public static final InputStream in = null;

// 标准输出(显示器)
public static final PrintStream out = null;

  System.err只是作为一个保留的属性而存在,现在几乎用不到。

  由于System.out是PrintStream(字节打印流)的实例化对象,而PrintStream又是OutputStream的子类,所以可以直接使用System.out直接为OutputStream实例化,这个时候的OutputStream输出的位置将变为屏幕。

  System.in对应的类型是InputStream,而这种输入流指的是由用户通过键盘进行输入(用户输入)。

  java本身并没有直接的用户输入处理,如果要想实现这种操作,必须使用java.io的模式来完成。

  如下面的例子:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;


public class Test {
    public static void main(String[] args) throws IOException {
        // System.in方式的键盘输入
        InputStream input = System.in;
        // 打开内存流
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        byte[] data = new byte[10];
        System.out.print("input:");
        int len = 0;
        while((len = input.read(data)) != -1) {
            out.write(data, 0, len);
            // 如果本次读入的字节没把数组装满,证明输入完了
            if(len < data.length) {
                break;
            }
        }
        input.close();
        out.close();
        // 打印存储在内存中的内容
        System.out.println("output:"+new String(out.toByteArray()));
    }
}

  虽然上面的例子可以实现从键盘输入并取到输入的内容,可这并绝不是我们常规的做法。

键盘接收数据

1. BufferedReader类

  BufferedReader类属于一个缓冲的输入流,它是一个字符流的操作对象。

  在java中对于缓冲流也分为两类:字节缓冲流(BufferedInputStream)、字符缓冲流(BufferedReader)。

  我们通过BufferedReader类的readLine()方法来获取键输入的数据。

// 这个方法可以读取键盘输入的一行数据,以回车为结尾
public String readLine() throws IOException

  在使用BuffeedReader之前我们再看一下它的的构造方法。

public BufferedReader(Reader in)

  显然,它需要一个传入 Reander类 的参数。

  而System.in是InputStream类的子类,所以就不能直接使用了,但是我们可以使用用InputStreamReader类(转换流)将 System.in 转换为一个 Reader 类来使用。

继承关系图

  我们看下面的例子:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Test {
    public static void main(String[] args) throws IOException {
        // BufferedReader字符缓冲输入流
        BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
        System.out.print("input:");
        String str = buf.readLine();
        System.out.print("output:"+str);
    }
}

  这比起上一节中的内存流配合System.in接受键盘数据的方式简单多了。bufferedReader解决了system.in原始化操作(先写到内存中,再从内存中进行读取转换)的复杂操作。

  可是,这种方法自从JDK1.5引入了Scanner类之后,就被人们迅速的摈弃了。

2. Scanner类

  Scanner类定义如下:

public final class Scanner implements Iterator<String>, Closeable

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

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

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

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

// 构造方法
// 注意,它直接接收 InputStream 类,所以我们可以直接传入 System.in
public Scanner(InputStream source)

2.1 Scanner接受键盘数据

  使用Scanner接收键盘数据实现如下:

import java.io.IOException;
import java.util.Scanner;


public class Test {
    public static void main(String[] args) throws IOException {

        // Scanner
        // 比起 BufferedReader 的构造要接收一个 Reader , Scanner的构造只需要接收一个 InputStream ,是在方便了很多
        Scanner scanner = new Scanner(System.in);
        System.out.print("input:");

        if(scanner.hasNext()) {
            System.out.print(scanner.next());
        }
        // 关闭流
        scanner.close();
    }

}

  不要被 next()方法和hasNext()方法的名字迷惑了,它俩本质上就是取得当前输入内容和判断是否当前有输入的内容。而方法名以 “next” 为主体的含义是以当前没有输入为立场:当前还没有输入,所以next个数据就是当前下一刻输入的数据。这点要切记。

2.2 Scanner类接收正则表达式

  Scanner类的hasNext()方法的判断依据除了类型,还可以是正则表达式,使用方法如下:

import java.io.IOException;
import java.util.Scanner;


public class Test {
    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入生日");
        // 输入要遵循的正则表达式
        if(scanner.hasNext("\\d{4}-\\d{2}-\\d{2}")) {
            System.out.print("生日为:"+scanner.next());
        } else {
            System.out.print("请输入正确的生日格式!");
        }
        scanner.close();
    }

}

2.3 Scanner类操作文件

  Scanner的构造方法是一个InputSream的对象,意味着它可以接受任意文件的字节输入流。使用如下:

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Scanner;

/**
 * 测试目录为 E:\IO\demo.txt
 */

public class Test {
    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(new FileInputStream(new File("E:\\IO\\demo.txt")));
        // 设置分隔符,以该分隔符为界,将输入流分割
        scanner.useDelimiter(" ");
        while(scanner.hasNext()) {
            System.out.println(scanner.next());
        }
        scanner.close();
    }
}

测试文件内容:

测试文件内容

运行结果:

运行结果

  从上面的几个例子我们可以看出,Scanner类完美的替代了BufferedReader类,并且完善了InputStream。所以以后关于键盘输出的场景,大可使用Scanner类,一定能满足你的要求。

猜你喜欢

转载自blog.csdn.net/weixin_40739833/article/details/80427644