(转载)java中的四大输入:System.in, Scanner, InputStreamReader, BufferedReader的用法与区别
链接:https://blog.csdn.net/qq_36631076/article/details/77006007
Java 的四个输入法:BufferedReader、InputStreamReader、Scanner 和 System.in。
1 System.in
System.in 返回的是 InputStream 指向命令行输入的字节流,InputStream 的 read 方法以字节流的方式来读取命令行的输入的数据。
查看源码(InputStream.java)我们常用的有:
1 int System.read() //以字节的方式读取输入的第一字符,返回该字符的ASCII码 2 3 int System.read(byte b[]) //以字节的方式把输入的字符放入byte数组中 4 5 int System.read(byte b[], int off, int len) //以字节的方式把输入的字符放入byte数组中 off是起始位置,len是最大读入的字节数。
使用实例:
// 以字节的方式读取输入的第一字符,返回该字符的ASCII码 int inputOne = System.in.read(); // 输入 abc System.out.println(inputOne); // 输出 97 (a 的 ascii 码)
byte[] b = new byte[5]; int length = System.in.read(b); // 输入 abc System.out.println(length); // 输出 4, 包含换行键 System.out.println(Arrays.toString(b)); // 输出 [97, 98, 99, 10, 0]
package test; import java.io.IOException; import java.util.Arrays; /* * 编程尝试System.in的用法 System.in返回的是InputStream指向命令行输入的字节流, 它的read方法以字节流的方式来读取命令行的输入的数据。 */ public class SystemModel { public static void main(String[] args) throws IOException { // 以字节的方式读取输入的第一字符,返回该字符的ASCII码。 1) public int System.read() int inputOne = System.in.read(); System.out.println(inputOne); // 将输入数据转化成字节数组str。 2) public int System.read(byte b[]) byte[] str = new byte[5]; //字节和字符不是同一个概念:byte & char int length = System.in.read(str); //以字节的方式把输入的字符放入byte数组中,返回数组长度 System.out.println(length); System.out.println(Arrays.toString(str)); // 3) public int System.read(byte b[], int off, int len),从off这个位置开始开始往数组中填数,off之前为0 byte[] str2 = new byte[5]; int len = System.in.read(str2, 2, 3); System.out.println(Arrays.toString(str2)); /* read 仅是读数据的操作 * System.in 中的read方法读取数据后,一旦读取,数据就被读走了 * 三个方法连用可以看出这一点 * 输入:abcdefghijklmnopq * 输出:97 //a的ascii码 5 //str转化成数组后的长度length [98, 99, 100, 101, 102] //str数组 [0, 0, 103, 104, 105] //str2数组 */ } }
2.BufferedReader
BufferedReader 从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。(通常和 InputStreamReader 连用,因为输入的数据是字节流,需要 InputStreamReader 将其转成成字符流)
BufferedReader 的构造函数:
1 private static int defaultCharBufferSize = 8192; //文本缓存大小的默认值 2 3 public BufferedReader(Reader in) { 4 this(in, defaultCharBufferSize); 5 } 6 7 public BufferedReader(Reader in, int sz)
BufferedReader 重要 API:
/** * Reads a line of text. A line is considered to be terminated by any one * of a line feed ('\n'), a carriage return ('\r'), or a carriage return * followed immediately by a linefeed. * * @param ignoreLF If true, the next '\n' will be skipped * * @return A String containing the contents of the line, not including * any line-termination characters, or null if the end of the * stream has been reached * * @see java.io.LineNumberReader#readLine() * * @exception IOException If an I/O error occurs */ String readLine(boolean ignoreLF) throws IOException // 这个是源码上的注释 public String readLine() throws IOException { //这里默认ignoreLF为false return readLine(false); } public int read(char cbuf[], int off, int len) //以字节的方式把输入的字符放入char数组中 off是起始位置,len是最大读入的字节数。 //The character read, as an integer in the range 0 to 65535 (<tt>0x00-0xffff</tt>), or -1 if the end of the stream has been reached public int read()
BufferedReader 的最大特点就是缓冲区的设置。通常 Reader 所作的每个读取请求都会导致对底层字符或字节流进行相应的读取请求,如果没有缓冲,则调用 read() 或 readLine() 都会导致从文件中读取字节,并将其转换为字符后返回,而这是极其低效的。使用BufferedReader 可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。(如果我们是AC题的时候,在内存允许的情况下把缓存区设置为输入的大小为最佳哈!!)
因此,建议用 BufferedReader 包装所有其 read() 操作可能开销很高的 Reader(如 FileReader 和 InputStreamReader)。例如:
BufferedReader in = new BufferedReader(new FileReader("foo.in")) //将缓冲指定文件的输入。
3.InputStreamReader
InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集
1 InputStreamReader (InputStream in) // 创建一个使用默认字符集的 InputStreamReader。 2 InputStreamReader (InputStream in, Charset cs) // 创建使用给定字符集的 InputStreamReader。 3 InputStreamReader (InputStream in, CharsetDecoder dec) // 创建使用给定字符集解码器的 InputStreamReader。 4 InputStreamReader (InputStream in, String charsetName) // 创建使用指定字符集的 InputStreamReader。
InputStreamReader 重要API
1 public int read() //以字节的方式读取输入的第一字符,返回该字符的ASCII码 2 3 public int read(char cbuf[]) //以字节的方式把输入的字符放入char数组中 4 5 public int read(char cbuf[], int offset, int length) //以字节的方式把输入的字符放入char数组中 offset是起始位置,length是最大读入的字节数。
每次调用 InputStreamReader 中的一个 read() 方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。 为了达到最高效率,可要考虑在 BufferedReader 内包装 InputStreamReader。例如:
BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); //用InputStreamReader来构造BufferedReader
InputStreamReader 最大的特点是可以指转换的定编码格式,这是其他类所不能的,从构造方法就可看出,这一点在读取中文字符时非常有用。
4.Scanner
java.util.Scanner 是Java5的新特征,主要功能是简化文本扫描,这个类最实用的地方表现在获取控制台输入。当通过 new Scanner(System.in) 创建一个Scanner,控制台会一直等待输入,直到敲回车键结束,把所输入的内容传给 Scanner,作为扫描对象。如果要获取输入的内容,则只需要调用 Scanner 的 nextLine() 方法即可。
Scanner也可以从字符串(Readable)、输入流、文件等等来直接构建Scanner对象,有了Scanner了,就可以逐段(根据正则分隔式)来扫描整个文本,并对扫描后的结果做想要的处理。
控制台扫描:
1 Scanner sc = new Scanner(System.in); 2 while (true) { 3 String line = sc.nextLine(); 4 if (line.equals("exit")) break; //如果输入为"exit",则退出 5 System.out.println("输入:" + line); 6 }
Scanner 默认使用空格作为分割符来分隔文本,但允许你指定新的分隔符:
1 // 默认以空格方式分割文本 2 Scanner sc = new Scanner("123 asdf sd 45 789 sdf asdfl,sdf.sdfl,asdf ......asdfkl las"); 3 4 // 以自己制定方式分割文本,支持正则表达式 5 //sc.useDelimiter(" |,|\\."); 6 7 while (sc.hasNext()) { 8 System.out.println(sc.next()); 9 }
重要API:
1 public Pattern delimiter() //返回此 Scanner 当前正在用于匹配分隔符的 Pattern。 2 3 public boolean hasNext() //判断扫描器中当前扫描位置后是否还存在下一段。 4 5 public boolean hasNextLine() //如果在此扫描器的输入中存在另一行,则返回 true。 6 7 public String next() //查找并返回来自此扫描器的下一个完整标记。 8 9 public String nextLine() // 此扫描器执行当前行,并返回跳过的输入信息。 10
11 public int nextInt() //扫描下一个整数,依次类推还有Double、Floate、Long等 12 ......
5.Scaner 和 BufferedReader 区别
Scanner 一个可以使用正则表达式来分析基本类型和字符串的简单文本扫描器。
BufferedReader 从字符输入流中读取文本,缓冲各个字符,从而提供字符、数组和行的高效读取。
- 1)Scanner 使用分隔符模式将其输入分解为标记,默认情况下该分隔符模式与空白匹配。然后可以使用不同的 next 方法将得到的标记转换为不同类型的值。
- 2)BufferedReader 可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了,默认大小为 8*1024 = 8192。
- 3)通常,Reader 所作的每个读取请求都会导致对基础字符或字节流进行相应的读取请求。因此,建议用 BufferedReader 包装所有其 read() 操作可能开销很高的 Reader(如 FileReader 和 InputStreamReader)。
6.BufferedReader 和 InputStreamReader 区别
BufferedReader 的作用是针对带有换行符的文本内容的按行读取,同时要正确处理各种字符集的文本数据。BufferedReader 一般创建时需要一个 Reader 的参数,由 Reader 去用流的方式读取数据。而 BufferedReader 只是解析流数据并组成一行一行的 String。而InputStreamReader 是 Reader 的一个子类 。
InputStreamReader 中通过 StreamDecoder 这个辅助类来完成的。 "An InputStreamReader is a bridge from byte streams to character streams: It reads bytes and decodes them into characters using a specified charset"