IO流(二)

转换流

读取键盘录入

需求一:读取一个键盘录入的数据,并打印在控制台上。
键盘本身就是一个标准的输入设备,对于java而言,对于这种输入设备都有对应的对象,这些对象在System类中。
默认的输入设备和输出设备都不需要关闭流,这个流会随着系统的出现而出现,随着系统的消失而消失。

public class ReadKey {

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

        readKey();

    }

//  读取一个键盘录入的数据,并打印在控制台上

    public static void readKey() throws IOException {

        InputStream in=System.in;

        int ch=in.read();//read()是一种阻塞式方法
        System.out.println(ch);

        int ch1=in.read();//阻塞式方法
        System.out.println(ch1);

        int ch2=in.read();//阻塞式方法
        System.out.println(ch2);    
/*      A   输入的A
        65  输出 A的ASCII码值
        13  输出的'\r'的ASCII码值
        10  输出的'\n'的ASCII码值
        */

/*      默认的输入设备和输出设备都不需要关闭流
        in.close();//不需要关,这个流会随着系统的出现而出现,随着系统的消失而消失

        //关了会发生异常:java.io.IOException: Stream closed
        InputStream in2=System.in;

        int ch3=in2.read();*/

    }
}

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

思路:
1.因为键盘录入的只读取一个字节,要判断是否是over,需要将读取到的字节拼成字符串
2.那就需要一个容器 StringBuilder
3.在用户回车之前将录入的数据变成字符串判断即可。
public class ReadKey {

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

        readKey2();
    }

    public static void readKey2() throws IOException {

        //1.创建容器
        StringBuilder sb=new StringBuilder();

        //2.获取键盘读取流
        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))
                    break;
                System.out.println(temp.toUpperCase());
                sb.delete(0, sb.length());
            }
            else
            //将读取到的字节存储到StringBuilder中
            sb.append((char)ch);
        }
    }
}

转换流

在读取键盘录入的第二个需求中,我们读取键盘输入的字节,但是需要将判断输入的是否是”over”,即需要将读取到的字节拼成字符串。在需求二里我们自己构建了一个从字节到字符的桥梁。在java中,已经定义好了这样一个桥梁:
转换流
InputStreamReader:字节流到字符流的桥梁。可使用指定的charset将要写入流中的字节解码成字符。它使用的字符集可以由名称指定或显式给定,否则接受平台默认的字符集。(解码)
OutputStreamWriter:字符流到字节流的桥梁。可使用指定的charset将要输出流的字符编码成字节。(编码)

同样的需求用转换流来做:获取用户键盘录入的数据,并将数据变成大写显示在控制台上。如果用户输入的是over 结束键盘录入。

public class TransStreamDemo {

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

        //字节流
        InputStream in=System.in;

        //转换流
        InputStreamReader isr=new InputStreamReader(in);

        //字符流
        BufferedReader bufr=new BufferedReader(isr);

        //字节流
        OutputStream out=System.out;

        //转换流
        OutputStreamWriter osw=new OutputStreamWriter(out);

        //字符流
        BufferedWriter bufw=new BufferedWriter(osw);

        String line=null;

        while((line=bufr.readLine())!=null){

            if("over".equals(line))
                break;
//          System.out.println(line.toUpperCase());

        /*  osw.write(line.toUpperCase());
            osw.flush();*/

            bufw.write(line.toUpperCase());
            bufw.newLine();
            bufw.flush();
        }
    }
}

更加简洁的代码如下:

public class TransStreamDemo{

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

        keyToConsole();
    }

    public static void keyToConsole() throws IOException {

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

字符本身来自于字节,但里面都是由纯文本的数据组成,用字符流操作起来非常方便,用几个需求的实现来感受一下:

package p1.transstream.demo;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
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 {

        /*1.需求:将键盘录入的数据写入到一个文件中  demo1
         * 
         * 2.需求:将一个文本文件内容显示在控制台上demo2
         * 
         * 3.需求:将一个文本文件中的内容复制到另一个文件中  demo3

         * 只需要改变流的源和目的
         * */
//      demo1();
//      demo2();
        demo3();

    }

    public static void demo3() throws IOException {

        BufferedReader bufr=new BufferedReader(new InputStreamReader(new FileInputStream("a.txt")));
        BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("b.txt")));

        String line=null;

        while((line=bufr.readLine())!=null){

            if("over".equals(line))
                break;

            bufw.write(line.toUpperCase());
            bufw.newLine();
            bufw.flush();
        }

    }

    public static void demo2() throws IOException {

        BufferedReader bufr=new BufferedReader(new InputStreamReader(new FileInputStream("a.txt")));
        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();
        }
    }

    public static void demo1() throws IOException {
        BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("a.txt")));

        String line=null;

        while((line=bufr.readLine())!=null){

            if("over".equals(line))
                break;

            bufw.write(line.toUpperCase());
            bufw.newLine();
            bufw.flush();
        }
    }

}

流的基本操作规律

IO流的操作规律

流对象太多,开发时不知道用哪个对象合适,这时要寻求流的基本操作规律。
想要知道开发时用到哪些对象。只需要通过四个明确即可:
1.明确源和目的(汇)

源:InputStream、Reader
目的: OutputStream、Writer

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

源:
|---是纯文本:Reader
|---否:InputStream

目的:
|---是纯文本:Writer
|---否:OutputStream

到这里,就可以明确需求中具体要使用哪个体系。

3.明确具体的设备

源设备:
    |---硬盘:File
    |---键盘:System.in
    |---内存:数组
    |---网络:Socket流

目的设备:
    |---硬盘:File
    |---控制台:System.out
    |---内存:数组
    |---网络:Socket流

4.是否需要其他额外功能

1.是否需要高效(缓冲区):
    是,就加上buffer
2.是否需要转换(转换流)

规律的体现

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

1.明确源和目的。
源:InputStream Reader
目的:OutputStream Writer
2.是否是纯文本:
是
源:Reader
目的:Writer

3.明确具备设备
    源:
        硬盘:File
    目的:
        硬盘:File

    FileReader fr=new FileReader("a.txt");
    FileWriter fw=new FileWriter("b.txt");

4.需要额外功能吗?
 需要高效
 BufferedReader bufr=new BufferedReader(new FileReader("a.txt"));
 BufferedWriter bufw=new BufferedWriter(new FileWriter("b.txt"));

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

1.明确源和目的。
    源:InputStream Reader
    目的:OutputStream Writer

2.是否是纯文本:是
    源:Reader
    目的:Writer

3.明确具备设备
源:
    键盘:System.in
目的:
    硬盘:File

    InputStream in=System.in;
    FileWriter fw=new FileWriter("b.txt");//这样做可以完成,但是麻烦。将读取的字节数据转成字符串,再由字符流转换为字节流

4.需要额外功能:
转换:
InputStreamReader isr=new InputStreamReader(System.in);
FileWriter fw=new FileWriter("b.txt");
高效:
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw=new BufferedWriter(new FileWriter("b.txt"));

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

1.明确源和目的。
    源:InputStream Reader
    目的:OutputStream Writer

2.是否是纯文本:是
    源:Reader
    目的:Writer

3.明确具备设备
源:
    硬盘:File
目的:
    控制台:System.out


FileReader fr=new FileReader("a.txt");
OutputStream out=System.out; 

4.是否需要额外功能:
需要,转换:
FileReader fr=new FileReader("a.txt");
OutputStreamWriter osw=new OuputStreamWriter(System.out);
需要,高效:
BufferedReader bufr=new BufferedReader(new FileReader("a.txt"));
BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(System.out));

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

1.明确源和目的。
    源:InputStream Reader
    目的:OutputStream Writer

2.是否是纯文本:是
    源:Reader
    目的:Writer

3.明确具备设备
源:
    键盘:System.in
目的:
    控制台:System.out


InputStream fr=System.in;
OutputStream out=System.out; 

4.是否需要额外功能:
需要转换,因为都是字节流,但是操作的却是文本数据,所以使用字符流操作起来更为便捷
InputStreamReader isr=new InputStreamReader(System.in); 
OutputStreamWriter osw=new OutputStreamWriter(System.out);
需要,高效:
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(System.out));

转换流的编码解码

需求五:将一个中文字符串数据按照指定的编码表写入到一个文本文件中。
按照“四个明确”分析:
1.目的 OutputStream Writer
2.是纯文本 Writer
3.设备:硬盘File
FileWriter fw=new FileWriter(“a.txt”);
fw.write(“你好”);

注意:既然需求中已经明确了指定编码表的动作。那就不可以使用FileWriter,因为FileWriter内部是使用默认的本地码表(这里是gbk)。
只能使用其父类。OutputStreamWriter。
OutputStreamWriter接收一个字节输出流对象。既然是操作文件,那么该对象应该是FileOutputStream

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

4.需要额外功能

高效:
BufferedWriter bufw=new BufferedWriter(new OutStreamWriter(new FileOutputStream("a.txt"),charsetName));

指定编码表的写出与读入代示例:

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 {

        InputStreamReader isr=new InputStreamReader(new FileInputStream("u8_1.txt"),"UTF-8");
        char[] buf=new char[1024];
        int len=isr.read(buf);
        String str=new String(buf,0,len);
        System.out.println(str);

        isr.close();

    }

    public static void readText_1() throws IOException {

        FileReader fr=new FileReader("gbk_1.txt");

        char[] buf=new char[1024];
        int len=fr.read(buf);
        String str=new String(buf,0,len);
        System.out.println(str);

        fr.close();

    }

    public static void writeText_3() throws IOException {

        OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("u8_1.txt"),"UTF-8");

        osw.write("你好");

        osw.close();

    }

    public static void writeText_2() throws IOException {

        OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("gbk_3.txt"),"GBK");

        FileWriter fw=new FileWriter("gbk_1.txt");

        /*这两句代码功能是等同的。
        FileWriter:其实就是转换流指定了本机默认码表的体现。而且这个转换流的子类对象,可以方便操作文本文件。
                    简单说:操作文本的字节流+本机默认的编码表
                    这是按照默认码表来操作文件的便捷类

        如果操作文本文件需要明确具体的编码,必须用转换流,不能再用FileWriter。*/

        osw.write("你好");

        osw.close();

    }

    public static void writeText() throws IOException {
        FileWriter fw=new FileWriter("gbk_1.txt");

        fw.write("你好");

        fw.close();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值