Java学习笔记03

Java学习——片段学习01(Java的接收输入)


一、Java接收键盘输入

Java接收控制台输入的三种方法:第一种 in/out,第二种 替换系统流,第三种 Scanner。

(1). in/out

in 和 out 为 System类的属性:
(1)public static final InputStream in//静态方法,用类名称直接调用,返回InputStream类,也就是说可以为InputStream实例化,System.in 是 InputStream类型,字节流,程序使用它可读取键盘输入的数据。“标准”输入流。此流已打开并准备提供输入数据。通常,此流对应于键盘输入或者由主机环境或用户指定的另一个输入源。
(2)public static final PrintStream out//静态方法,用类名称直接调用,返回PrintStream类,也就是说可以为OutputStream实例化,System.out 是 PrintStream类型(是OutputStream的子类),字节流,程序使用它可将数据输出到显示屏上。“标准”输出流。此流已打开并准备接受输出数据。通常,此流对应于显示器输出或者由主机环境或用户指定的另一个输出目标。

例:

// System.in和System.out方法
   //缺点一: 该方法能获取从键盘输入的字符,但只能针对一个字符的获取
   //缺点二: 获取的只是char类型的。如果想获得int,float等类型的输入,比较麻烦。
  public static void CharTest(){ 
    try{
      System.out.print("Enter a Char:");
      char i = (char)System.in.read();
      System.out.println("Yout Enter Char is:" + i);
    }
    catch(IOException e){
      e.printStackTrace();
    }    
  }

System 是一个类,属于java.lang包,表示系统类
定义如下:

public final class System extends Object		//此类为最终类,不能被继承。

它有以下两个重要的成员变量:
(1)in:它是一种输入流对像,它的源是键盘,可以读取用户从键盘输入的数据,在读取数据时会引起堵塞,直到用户按下Enter键,读取方法:

public int read(char c[],int off,int len)
public int read(char c[])

(2)out:它是一种输出流对象,它的目的地是命令行窗口,写入方法:

public void write(char c[],int off,int len)
public void write(char c[])

我们最常用的也就是输出流的System.out打印至控制台,实际上在JAVA中也对IO给予了一定的支持,System.in, System.out, System.err这3个流同样是常见的数据来源和数据流目的地。JVM启动的时候通过Java运行时初始化这3个流,所以不需要初始化它们。


System.err和System.out的区别
java API文档中给出的解释是:out为“标准输出流”,err为“标准错误输出流”。
在eclipse里运行时差别就是,二者显示的颜色有所区别,err输出显示为红色 。
err.println输出的字符串位置会随机出现。但是,err.println输出的字符串之间的相对位置不会改变,System.out在JVM和操作系统都具有缓存功能,就是你输出的东西不一定实时输出,有时候会积攒到一定数量才会输出;System.err会实时输出,单独使用的话可能感觉不到,如果两种方式混合使用就会发现了 。

(2).替换系统流

把一个新的InputStream设置给System.in或者一个新的OutputStream设置给System.out,之后的数据都将会在新的流中进行读取、写入。
可以使用System.setIn(), System.setOut()方法设置新的系统流(这二个方法均为静态方法,内部调用了本地native方法重新设置系统流)。请记住,需要在JVM关闭之前刷新System.out(调用flush()),确保System.out把数据输出到了文件中。

例:

 // InputStreamReader和BufferedReader方法
   // 优点: 可以获取键盘输入的字符串
   // 缺点: 如何要获取的是int,float等类型的仍然需要转换
  public static void ReadTest(){
    System.out.println("ReadTest, Please Enter Data:");
    InputStreamReader is = new InputStreamReader(System.in); //new构造InputStreamReader对象
    BufferedReader br = new BufferedReader(is); //拿构造的方法传到BufferedReader中,此时获取到的就是整个缓存流
    try{ //该方法中有个IOExcepiton需要捕获
      String name = br.readLine();
      System.out.println("ReadTest Output:" + name);
    }
    catch(IOException e){
      e.printStackTrace();
    }    
  }

其中: 在BufferedReader中包装InputStreamReade,为了获得更高效率①。
InputStreamReader: 是从字节流到字符流②的桥接器,能将字节流输出为字符流并且能为字节流指定字符集(如果不指定的话将采用底层操作系统的默认编码方式)。可一个个的输出字符,它封裝了InputStream在里头,以较高级的方式一次读取一个个字符。

BufferedReader: 它则是比InputStreamReader更高级,它封裝了StreamReader类,一次读取一行的字符提供通用的缓冲方式文本读取,readLine读取一个文本行, 从字符输入流中读取文本,缓冲各个字符,从而提供字符、数组和行的高效读取。

java.io下面有两个抽象类:InputStream和Reader也就是分别表示字节流和字符流, InputStream是表示字节输入流的所有类的超类,提供的是字节流的读取,而非文本读取,这是和Reader类的根本区别。
Reader是用于读取字符流的抽象类,通常Reader 所作的每个读取请求都会导致对底层字符或字节流进行相应的读取请求,如果没有缓冲则每次调用 read() 或 readLine() 都会导致从文件中读取字节,并将其转换为字符后返回,而这是极其低效的。即用Reader读取出来的是char数组或者String ,使用InputStream读取出来的是byte数组。


为了获得最高效率,请考虑在BufferedReader中包装InputStreamReader?

从read()方法理解,若使用InputStreamReader的read()方法,可以发现存在每2次就会调用一次解码器解码,但若是使用 BufferedReader包装InputStreamReader后调用read()方法,可以发现只会调用一次解码器解码,其余时候都是直接从BufferedReader的缓冲区中取字符即可

从read(char cbuf[], int offset, int length)方法理解,若使用InputStreamReader的方法则只会读取leng个字符,但是使用BufferedReader类则会读取读取8192个字符,会尽量提取比当前操作所需的更多字节;

例如文件中有20个字符,我们先通过read(cbuf,0,5)要读取5个字符到数组cbuf中,然后再通过read()方法读取1个字符。那么使用InputStreamReader类的话,则会调用一次解码器解码然后存储5个字符到数组中,然后又调用read()方法调用一次解码器读取2个字符,然后返回1个字符;等于是调用了2次解码器,若使用BufferedReader类的话则是先调用一次解码器读取20个字符到字符缓冲区中,然后复制5个到数组中,在调用read()方法时,则直接从缓冲区中读取字符,等于是调用了一次解码器

因此可以看出BufferedReader类会尽量提取比当前操作所需的更多字节,以应该更多情况下的效率提升;
因此在设计到文件字符输入流的时候,我们使用BufferedReader中包装InputStreamReader类即可。

字节流到字符流的桥梁怎么理解?

1、计算机存储的单位是字节,如尽管txt文本中有中文汉字这样的字符,但是对计算机而言,其是字节形式存在的。
2、字节流读取是单字节读取,但是不同字符集解码成字符不通过个数,因此字节流读取会报错。
3、 那么就需要一个流把字节流读取的字节进行缓冲而后在通过字符集解码成字符返回,因而形式上看是字符流。
4、InputStreamReader流就是起这个作用,实现从字节流到字符流的转换。

(3).Scanner

Scanner是Java5的新特征,主要功能是简化文本扫描。Scanner的中文意思就是扫描仪,也就是将一份数据从一个地方扫描并显示到另外一个地方。一个可以使用正则表达式来解析基本类型和字符串的简单文本扫描器。

例:

//Scanner类中的方法
   //优点一: 可以获取键盘输入的字符串
   //优点二: 有现成的获取int,float等类型数据,非常强大,也非常方便;
  public static void ScannerTest(){
    Scanner sc = new Scanner(System.in);
    System.out.println("ScannerTest, Please Enter Name:");
    String name = sc.nextLine();  //读取字符串型输入
    System.out.println("ScannerTest, Please Enter Age:");
    int age = sc.nextInt();    //读取整型输入
    System.out.println("ScannerTest, Please Enter Salary:");
    float salary = sc.nextFloat(); //读取float型输入
    System.out.println("Your Information is as below:");
    System.out.println("Name:" + name +"\n" + "Age:"+age + "\n"+"Salary:"+salary);
  }

Scanner使用分隔符模式将其输入分解为标记,默认情况下该分隔符模式与空白匹配。然后可以使用不同的 next 方法将得到的标记转换为不同类型的值。当通过new Scanner(System.in)创建一个Scanner,控制台会一直等待输入,直到敲回车键结束,把所输入的内容传给Scanner,作为扫描对象。而且Scanner类有一个假设,在输入结束时会抛出IOException,而Scanner类会把这个异常吞掉。

经常有人说使用Scanner的原因是因为它使用简便,不如说Scanner的构造器支持多种方式,构建Scanner的对象很方便。可以从字符串(Readable)、输入流、文件等等来直接构建Scanner对象,有了Scanner了,就可以逐段(根据正则分隔式)来扫描整个文本,并对扫描后的结果做想要的处理。

scanner好比一个带游标或者指针的扫描仪,调用其hasNextLine()好比将游标向前探索直到遇到一个换行符,如果这个过程中遇到字符串对象则返回true并且游标复位。调用其nextLine()方法其实就是游标向前探索直到遇到一个换行符,此时并不复位,而是游标直接定位到目标数据的下一行,并返回探索过程中检测到的数据包括空格。


java里常使用的方法next() 与 nextLine() 区别

next():
1、一定要读取到有效字符后才可以结束输入。
2、对输入有效字符之前遇到的空白,next() 方法会自动将其去掉
3、只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。next() 不能得到带有空格的字符串。

nextLine():
1、以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符。
2、可以获得空白


总结

浅探java从键盘输入的三个方法:第一种 in/out,第二种 替换系统流,第三种 Scanner。 综上所述,第一种仅支持字符输入,第二种更为广泛,支持字符串的输入,对整型,浮点型还有欠缺;第三种就比较简便,适用性更强。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值