Java笔记-I/O转换流(字符流)

前景提要

点击 跳转到我的笔记:Java笔记-I/O字节流


转换流基本介绍

转换流包含:

1.OutputStreamWriter输出流
2.InputStreamReader输入流

如果构造器里面不传入编码,则使用平台默认编码

转换流本质:

把字节流+编码表,转换成,字符流。


在《Java网络编程》中,有这样一段话:

“Reader和Writer最重要的子类是InputStreamReaderOutputStreamWriter类。

InputStreamReader类包含了一个底层输入流,可以从中读取原始字节。它根据指定的编码方式,将这些字节转换为Unicode字符。

OutputStreamWriter从运行的程序中接收Unicode字符,然后使用指定的编码方式将这些字符转换为字节,再将这些字节写入底层输出流中。”


转换流的特点:

  1. 其是字符流和字节流之间的桥梁

  2. 可对读取到的字节数据经过指定编码转换成字符

  3. 可对读取到的字符数据经过指定编码转换成字节


OutputStreamWriter

简单使用举例:

public static void main(String[] args) {
    try {
        OutputStreamWriter osw = new OutputStreamWriter(
            new FileOutputStream("D:\\a.txt"));
        osw.write(97);
        osw.write('小');
        osw.write("龙的传人");
        osw.write("精灵宝可梦".toCharArray());
        osw.write("桃花潭水深千尺", 2, 2);
        osw.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

//运行结果:
//a小龙的传人精灵宝可梦潭水

//如果想每次在文件末尾写入数据的话
//OutputStreamWriter没提供构造方法
//我们使用FileOutputStream为我们提供的构造方法即可
//new FileOutputStream("a.txt", true)   即可

InputStreamReader

简单使用举例:

public static void main(String[] args) {
    try {
        // 1.一次读一个字符
        InputStreamReader isr1 = new InputStreamReader(
            new FileInputStream("D:\\Demo.java"));
        int ch = -1;
        while ((ch = isr1.read()) != -1) {
            System.out.print((char) ch);
        }
        isr1.close();

        // 2.一次读一个字符数组
        InputStreamReader isr2 = new InputStreamReader(
            new FileInputStream("D:\\Demo.java"));
        char[] cs = new char[100];
        int total = -1;
        while ((total = isr2.read(cs)) != -1) {
            System.out.print(new String(cs, 0, total));
        }
        isr2.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

//提示:转换流可以读字符,也就是可以处理中文,不会乱码。

转换流乱码问题

1.先向系统中写入UTF-8编码的文件
代码演示:

public static void main(String[] args) {
    try {
        //按UTF-8编码
        OutputStreamWriter osw = new OutputStreamWriter(
            new FileOutputStream("D:\\a.txt"), "UTF-8");
        String str = "一失足成千古风流人物";
        osw.write(str);
        osw.close();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
//new OutputStreamWriter(new FileOutputStream("xx"), "UTF-8");
//也就是OutputStreamWriter的构造方法可以控制编码格式

2.用Java读取文件的内容输出到控制台
代码演示:

public static void main(String[] args) {
    try {
        //按UTF-8解码
        InputStreamReader isr = new InputStreamReader(
            new FileInputStream("D:\\a.txt"), "UTF-8");
        int total = -1;
        char[] cs = new char[100];
        while ((total = isr.read(cs)) != -1) {
            System.out.print(new String(cs, 0, total));
        }
        isr.close();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
//同OutputStreamWriter
//new InputStreamReader(new FileInputStream("xx"), "UTF-8");
//也就是InputStreamReader的构造方法可以控制解码格式

字节流和字符流的差异:

问题1:混着用会有什么问题?为什么?
答:字节流去复制文本文件没问题,复制字节码文件也没问题。
字符流复制文本文件没问题,复制字节码文件比原来大,而且文件损坏。
原因:因为字符流每次拿取一个字符,而我们字节码文件里面没有字符,所以导致把字节当做字符处理,莫名其妙多了很多字符,而这些字符导致了字节码文件的字节混乱,无法使用

问题2:什么时候用字节流?什么时候用字符流?
答:用windows本地记事本打开文件
如果看得懂就用字符流
如果看不懂就用字节流
如果不知道 就用字节流(万能流)


FileReader类和FileWriter类

方法都是从转换流继承过来,自己没有新方法

1.字符输入流 FileReader 类

FileReader 类是读取字符流的抽象类,常用方法如下:

方法名称 说明
int read() 从输入流中读取单个字符
int read(byte[] c) 从输入流中读取 c.length长度的字符,保存到字符数组 c 中,返回实际读取的字符数
int read(char[] c, int off, int len) 从输入流中读取最多 len 长度的字符,保存到字符数组 c 中,保存的位置从 off 位置开始,返回实际读取的字符长度
void close() 关闭流

FileReader 类,字符输入流,代码演示:

public static void main(String[] args) {
    try {
        // InputStreamReader isr = new InputStreamReader(new BufferedInputStream(new FileInputStream("D:\\a.txt")));
        // 下面一行代码是上面的代码的简化写法
        // 使用默认的缓冲区大小 和 默认的编码表
        FileReader fr = new FileReader("D:\\a.txt");
        int total = -1;
        char[] cs = new char[100];
        while ((total = fr.read(cs)) != -1) {
            System.out.println(new String(cs, 0, total));
        }
        fr.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

2.字符输出流 FileWriter 类

FileWriter类是向文件写入数据的字符流,常用方法如下:

方法名称 说明
write(String str) 将 str 字符串里包含的字符输出到指定的输出流中
write(String str, int off, int len) 将 str 字符串里从 off 位置开始长度为 len 的字符输出到输出流中
void close() 关闭输出流
void flush() 刷新输出流

FileWriter 类,字符输出流,代码演示:

public static void main(String[] args) {
    try {
        // OutputStreamWriter isr = new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream("D:\\a.txt")));
        // 下面一行代码是上面的代码的简化写法
        // 使用默认的缓冲区大小 和 默认的编码表
        FileWriter fw = new FileWriter("D:\\a.txt", true);
        fw.write("xxxxx");
        fw.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
//如果像我一样FileWriter fw = new FileWriter("D:\\a.txt", true);
//写true 则写在文章末尾; 不写的话,覆盖文章,从头开始写

缓冲字符流

BufferedWriter缓冲字符输出流

输出换行符的方法

//1.缓冲字符流为我们提供的方法
bw.newLine();
//2.动态获取换行符并输出
bw.write(System.getProperty("line.separator"));
//3.直接输出操作系统的换行符(我这里输出的Windows的)
bw.write("\r\n");

BufferedWriter简单示范

代码如下:

public static void main(String[] args) {
    try {
        // 3中换行方法演示
        BufferedWriter bw = new BufferedWriter(
            new FileWriter("D:\\a.txt"));
        bw.write("xxx");
        // 1 跨平台可用,写起来麻烦
        bw.write(System.getProperty("line.separator"));
        bw.write("yyy");
        // 2 推荐
        bw.newLine();
        bw.write("zzz");
        // 3 跨平台不可用
        bw.write("\r\n");
        bw.write("结束");
        bw.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

BufferedReader缓冲字符输入流

有一个新的方法可用:

方法名称 说明
String readLine() 读取一个文本行。通过下列字符之一即可认为某行已终止:\r\n\r\n,或回车后直接跟着换行。
返回:包含该行内容的字符串,不包含任何终止符,所以每读取到一行,自己手动添加换行符;如果已到达流末尾,返回 null

代码演示:

public static void main(String[] args) {
    try {
        BufferedReader br = new BufferedReader(
            new FileReader("D:\\a.txt"));
        String line = null;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

//注意:
//line = br.readLine() != null
//是 != null ; 不是 != -1 了
//切记切记!




你可能感兴趣的:(JavaSE,JavaSE-I/O流)