13.IO(二)【键盘录入】【转换流】【流的操作规律】

来源:互联网 发布:淘宝店铺降权截图 编辑:程序博客网 时间:2024/04/28 02:37


一、键盘录入

   1.  标准输入流和标准输出流

       System.in:输入流。对应的标准输入设备,键盘。类型是InputStream。

       System.out:输出流。对应的标准输出设备,控制台。类型是PrintStream。

   2.   单字节录入与整行录入

       单字节录入:当使用标准输入流读取键盘录入的数据时,只能一个字节一个字节的进行录入。

       整行录入:为了提高键盘录入的效率,可以自定义一个数组存储每一行数据。当一行数据录入完后,整体操作这一行数据。这 

                        个原理和字符流读取一行数据的原理一样,即readLine()方法。

     

<span style="font-size:18px">/* * 例子:读取一个键盘录入的数据。并打印在控制台上。 *  * 键盘本身就是一个标注呢输入设备。 * 对于Java而言,对于这种输入设备都有对应的对象。 */import java.io.IOException;import java.io.InputStream;public class ReadKey {public static void main(String[] args) throws IOException {//'\r','\n'的ASII值//System.out.println((int)'\r');//13//System.out.println((int)'\n');//10//readKey();readKey2();}//整行录入public static void readKey2() throws IOException {/* * 获取用户键盘录入的数据。 * 并将数据变成大写显示在控制台上。 * 如果用户输入的是over,结束键盘录入。 *  * 思路: * 1.键盘录入只读取一个字节。要判断是否是over,需要先将读取到的字节拼成字符串。 * 2.那就需要一个容器。StringBuilder * 3。在用户回车之前,将录入的数据变成字符串,判断即可。 *///1.创建容器。StringBuilder sb = new StringBuilder();//获取键盘读取流。InputStream in = System.in;//3.定义变量记录读取到的字节,并循环获取。int ch = 0;while((ch=in.read())!=-1){//在存储时要判断是否是换行标记,因为换行标记不需要存储,if(ch=='\r')continue;if(ch=='\n'){String temp = sb.toString();if("over".equals(temp))//如果输入的是over,结束。break;//将字符串变成大写输出。System.out.println(temp.toUpperCase());sb.delete(0, sb.length());}else{//将读取到的字节存储到StringBuilder中。sb.append((char)ch);//System.out.println(ch);}}}/**一个字节一个字节读取 * @throws IOException */public static void readKey() throws IOException {InputStream in = System.in;//说明:系统回车符是\r\n,读取时这两个字符也会被读取,ASII值为13,10int ch = in.read();//阻塞式方法。遇到流末尾或者抛出异常之前,一直阻塞。System.out.println(ch);int ch1 = in.read();System.out.println(ch1);int ch2 = in.read();System.out.println(ch2);//in.close();//System.in流对象就只有一个,关闭后,不能读取。键盘录入。所以不需要关闭。//这是系统默认输入设备。//默认输入,输出设备都不需要关闭,int ch3 = in.read();System.out.println(ch3);}}</span>

 

3.  能不能直接使用readLine方法来完成键盘的整行录入呢?

    答:readLine方法是BufferedReader类中的方法,而键盘录入使用的是字节流InputStream中的方法。

           如何将字节流转换成字符流,再使用字符流缓冲区的readLine方法,这是需要考虑的问题。

           如果使用转换流,这个问题将迎刃而解。

二、转换流

1. 概述

    转换流可以实现字节流和字符流之间的转换,是字符流和字节流之间的桥梁,方便了两者之间的操作。

2. 转换流

    InputStreamReader:字节流转换为字符流,解码。

   OutputStreamWriter:字符流转换为字节流,编码。

3.  转换流=字节流+编码表。

     解释:System.in是字节流。读取文本时,需要分两次读取,而InputStreamReader是字符流,读取文本时一次读取就行了。但是

                底层还是调用了字节流读取,只不过读取时将两次读取到的字节流和编码表对照,并返回字节对应的文本。

   

附常见编码表:

ASCII:美国标准信息交换码    用一个字节的7位可以表示。

ISO8859-1:拉丁码表,欧洲码表,用一个字节的8位表示。

GB2312:中国的中文编码表。

GBK:中国的中文编码表升级版,融合了更多的中文文字符号。

Unicode:国际编码表,融合了多种文字,所有文字都用两个字节来表示,java

语言中使用的就是Unicode编码。

UTF-8:最多用三个字节来表示一个字符。

4. 什么时候使用转换流?

   1)  源或者目的对应的设备是字节流,但是操作的却是文本数据,可以使用转换流。方便操作。

   2)  一旦操作文本涉及到指定的编码表,必须使用转换流。

 

5. 转换流使用步骤(以InputStreamReader为例):

    ①获取键盘键盘读取流

        InputStream in = System. In;

    ②使用转换流将字节流转换为字符流

        InputStreamReader isr = newInputStreamReader(in);

    ③为了提高效率,可以使用字符流缓冲区

        BufferedReader bdr = new BufferedReader(isr);

 

以上步骤的简写方式:BufferedReaderin=newBufferedReader(new InputStreamReader(System.in));

 

例子:需求:

         获取用户键盘录入的数据,并将数据变成大写显示在控制台上。如果用户输入的是over,

     结束键盘录入。

<span style="font-size:18px">import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.OutputStreamWriter;//转换流 public class TransStreamDemo2 {public static void main(String[] args) throws IOException {/* // 字节流InputStream in = System.in;// 将字节流转换成字符流,转换流。这样才能调用字符流中的readLine()方法。InputStreamReader isr = new InputStreamReader(in);BufferedReader bufr = new BufferedReader(isr);// 标准输出流。OutputStream out = System.out;// 字符流-->字节流OutputStreamWriter osw = new OutputStreamWriter(out);BufferedWriter bufw = new BufferedWriter(osw);*/// 简化形式// 缓冲区(转换流(标准输入流))BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));// 缓冲区(转换流(标准输出流))BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));String line = null;while ((line = bufr.readLine()) != null) {if ("over".equals(line))break;bufw.write(line.toUpperCase());bufw.newLine();bufw.flush();}}}</span>


 

三、流的操作规律

           因为流对象太多,开发时不知道用哪个对象。所以就总结了流的操作规律。

流的操作规律:四个明确 

1.明确源和目的

        源:InputStream    Reader

        目的:OutputStream  Writer

2.明确源和目的是否是纯文本数据

        源:是否是纯文本

            是。 Reader

            否。InputStream

        目的:是否是纯文本?

            是。Writer

            否。OutputStream       

3.明确具体的设备

        源:

            硬盘:File

            键盘:System。in

            内存:数组、

            网络:Socket流

           

        目的:

            硬盘:File

            控制台:System。out

            内存:数组

            网络:Socket流 

4.明确是否需要额外的功能

        1)是否需要需要高效(缓冲区)

            是。加上Buffered

        2)是否需要转换。

            是。转换流。

   

需求1:复制一个文本文件。

    1.明确源和目的

        源:InputStream       Reader

        目的:OutputStream     Writer

    2.明确数据是否为纯文本数据。

        源:

            是纯文本。Reader

           

        目的:

            是纯文本。Writer

    3.明确具体的设备

        源:

            硬盘:File

        目的:

            硬盘:File

           

        FileReader fr = newFileReader("a.txt");

        FileWriter fw = newFileWriter("b.txt");

    4.是否需要额外功能         

        需要,需要高效。加上Buffered

        BufferedReader bufr = newBufferedReader(new FileReader("a.txt");

        BufferedWriter bufw = newBufferedWriter(new FileWriter("b.txt");

 

需求2:读取键盘录入的信息,并写入到文件中。

   

    1.明确源和目的:

        源:InputStream         Reader

        目的:OutputStream       Writer

    2.明确数据是否为纯文本数据。

        是。

        源:Reader

        目的:Writer

    3.明确具体设备:

        源:

            键盘:System。in

        目的:

            硬盘:File

        InputStream fr = System.in;

        FileWriter fw = new Writer("b.txt");

        这样做可以完成,但是麻烦。将读取的字节数据专程字符串。

再由字符流操作。

       

    4.是否需要额外功能。

        需要,转换。将字节流专程字符流。因为明确的源是Reader,

这样操作文本数据最便捷。

            所以要将已有的字节流专程字符流。使用字节-->字符 。       InputStreamReader

        InputStreamReader isr = newInputStreamReader(System.in);

        FileWriter fw = FileWriter("b.txt");

   

        还需要额外功能么?

        需要,高效。

        BufferedReader bufr = newBufferedReader(new InputStreamReader(System.in);

        BufferedWriter bufw = newBufferedWriter(new FileWriter("b.txt");

       

需求3:将一个文本文件数据显示在控制台上。

   

    1.明确源和目的

        源:InputStream      Reader

        目的:OutputStream    Writer

    2.明确数据是否是纯文本。

        是。

        源:Reader

        目的:Writer

    3.明确具体设备

        源:

            硬盘:File

        目的:

            控制台:System。out

    FileReader fr = newFileReader("a.txt");

    OutputStream out = System.out;//父类是PrintStream

   

    4.需要额外功能么?

        需要。转换。

        FileReader fr = newFileReader("a.txt");

        OutputStreamWriter osw = newOutputStreamWriter(System.out);

        还需要高效。

       BufferedReader bufr = new BufferedReader(new FileReader("a.txt");

       BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out);

       

需求4:读取键盘录入数据。显示在控制台上。  

    1.明确源和目的

        源:InputStream       Reader

        目的:OutputStream     Wirter

    2.明确数据是否为纯文本。

        是。

        源:Reader

        目的:Writer

    3.明确具体设备

        源:

            键盘:System.in

        目的:

            控制台:System。out

    InputStream in = System.in;

    OutputStream out = System.out;

   

    4.明确是否需要额外功能。

        需要。转换。因为都是字节流,但是操作的却是文本数据,

        所以使用字符流操作起来更为便捷。

        InputStreamReader isr = new InputStreamReader(System.in);

        OutputStreamWriter osw = new OutputStreamWriter(System.out);

   

        为了将其高效操作,

        BufferedReader bufr = newBufferedReader(new InputStreamReader(System.in);

        BufferedWriter bufw = new BufferedWriter(newOutputStreamWriter(System.out);

 

需求5.将一个中文字符串数据按照指定的编码表写入到一个文本文件中。   

   

    1.目的:OutputStream    Writer

    2.是纯文本,   Writer

    3.设备:硬盘 File

    FileWriter fw = newFileWriter("a.txt");

    fw.write("你好");

   

    注意:既然需求中明确了指定的编码表。就不能再使用FileWriter,因为FileWriter内部使用默认的本地码表,只能使用其父类OutputStreamWriter.

        OutputStreamWriter接收一个字节流对象,既然是操作文件,那么对象应该是FileOutputStream。

        OutputStreamWriter osw = newOutputStreamWriter(new FileOutputStream("a.txt"),charsetName);

   

     若需要使用缓冲区,则

     BufferedWriterbufw = new BufferedWriter(new OutputStreamWriter(newFileOutputStream("a.txt"),charsetName));

    代码实现:

<span style="font-size:18px">//编码解码/* * 我们用的是默认的编码表。现在要按照指定的码表 */public class TransStreamDemo3 {public static void main(String[] args) throws IOException {//WriteText();//WriteText_2();//WriteText_3();//readText_1();readText_2();}public static void readText_2() throws IOException {//如果GBK编码的文件按照utf-8编码表来解,会得出未知字符。InputStreamReader isr = new InputStreamReader(new FileInputStream("gbk.txt"),"utf-8");char[] buf = new char[10];int len = isr.read(buf);System.out.println(new String(buf,0,len));isr.close();}public static void readText_1() throws IOException {//解码时要按照对应的编码表来解码。FileReader fr = new FileReader("u8.txt");char[] buf = new char[10];int len = fr.read(buf);System.out.println(new String(buf,0,len));fr.close();}public static void WriteText_3() throws IOException, FileNotFoundException {//指定u8编码表,结果相同,但是文件大小不一样。u8编码表用3个字节来表示一个中文。OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("u8.txt"),"UTF-8");osw.write("你好3");osw.close();}public static void WriteText_2() throws IOException {//转换流可以指定编码表。OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gbk_2.txt"),"GBK");FileWriter fw = new FileWriter("gbk.txt");/* * 这两句代码的功能是等同的。 * FileWriter:其实就是转换流指定了本机默认码表的体现。而且这个转换流的子类对象,可以方便的操作文本文件。 * 简单说就是,操作文件的字节流+本机默认编码表。 * 这是按照默认码表来操作文件的便捷类。 *  * 如果操作文件需要明确具体的编码,FileWriter就不行了,必须用字节流。 */osw.write("你好2");osw.close();}/** * @throws IOException */public static void WriteText() throws IOException {//等效于OutputStreamWriter = new OutputStreamWriter(new FileOutputStream("gbk_2.txt"));FileWriter fw = new FileWriter("gbk.txt");fw.write("你好");fw.close();}}</span>

 


原创粉丝点击