欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-03-06 16:18:02
...

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 类来使用。

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

  我们看下面的例子:

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();
    }
}

测试文件内容:

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

运行结果:

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

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