IO流(三) --- 字符流

字符流


字符流结构图:

在这里插入图片描述


为什么需要字符流,用字节流不可么?

通过字节流来进行文件复制的话是没有任何问题的,但是,当你想通过程序来观看文件的内容时(比如将文件中的内容打印到控制台)就很大几率出现乱码现象,这是为什么呢?如果文件中只有ASCII码表中的字符是没有任何问题的,但是如果文件中包含中文的话就有乱码现象出现,这是因为在给文本进行编码和解码的编码表不同造成的,或者是通过一个字节的方式来读取内容的,因为中文是用gb系列编码或Unicode编码,在gb系列编码中中文占用两个字节,在Unicode中中文至少占用3个字节,当你是用字节流进行读取,字节流以字节为单位传输,并不知道你所读取的内容是什么编码类型,所以也就无法正确解读;为了解决乱码问题,让我们能够方便的阅读,字符流就可以很好的解决这一问题;

字符流 = 字节流 + 编码表;


编码表:

ASCII表:a --> 97,A --> 65, 0 --> 48

GBK编码:一个中文占两个字节,包含ASCII中的所有字符;

UTF-8编码:一个中文占3个字节,可以兼容世界上很多国家的语言;国际通用编码;


编码和解码:

  • 编码:

    1. 表面含义:就是把我们能看懂的转成我们看不懂的;
    2. 本质:本质就是把字符串转成字节数组;
    3. 方法:
    byte[] getBytes() : 使用平台(idea/Eclipse)的默认字符集将该 String编码为一系列字节
        
    byte[] getBytes(String charsetName) : 使用指定的字符集将该 String编码为一系列字节
    

  • 解码:

    1. 表面含义:就是把看不懂的转成我们能看懂的;
    2. 本质:本质就是把字节数组转成字符串;
    3. 方法:
    String(byte[] bytes) : 使用平台的默认字符集解码指定的字节数组来创建字符串
        
    String(byte[] bytes, String charsetName) : 通过指定的字符集解码指定的字节数组来创建字符串
    

  • 出现乱码的原因:

    编码和解码使用的编码表不一致;


字符输入流(Reader)


概述:

Reader是字符输入流的抽象根类,其子类有InputStreamReaderFileReaderBufferedReader等;


常用方法:

方法 方法说明
int read() 从源文件中读取一个字符的数据
int read(char[] cbuf) 从源文件中读取一个字符数组的数据
int read(char[] cbuf, int offset, int length) 从源文件中读取一个字符数组的一部分数据
void close() 关闭与流相关的资源

字符输出流(Writer)


概述:

Writer是字符输出流的抽象根类,其子类有OutputStreamWriterFileWriterBufferedWriter等;


常用方法:

方法 方法说明
void write(int c) 向目标文件写入一个字符
void write(char[] cbuf) 向目标文件中写入一个字符数组
void write(char[] cbuf, int off, int len) 向目标文件中写入一个字符数组的一部分
void write(String str) 向目标文件中写入一个字符串
void write(String str, int off, int len) 向目标文件中写入一个字符串的一部分
void flush() 将数据从缓冲区写入到目标文件中
void close() 先将数据从缓冲区写入到目标文件中,然后释放资源

转换流


概述:

转换流是字节流转换成字符流的桥梁,它可以根据指定的字符编码来将字节流转换成字符流,也可以采用平台默认的字符编码;


转换输入流(InputStreamReader)


概述:

InputStreamReader是将字节输入流转换成字符输入流;其继承自Reader抽象类,所以拥有Reader中的所有方法;


构造方法:

InputStreamReader(InputStream in) : 使用默认字符编码创建InputStreamReader对象
    
InputStreamReader(InputStream in,String chatset) : 使用指定的字符编码创建InputStreamReader对象

转换输出流(OutputStreamWriter)


概述:

OutputStreamWriter可以将字节输出流转换成字符缓冲流;其继承自Writer抽象类,所以拥有Writer中的所有方法;


构造方法:

OutputStreamWriter(OutputStream out) : 使用默认字符编码创建OutputStreamWriter对象
    
OutputStreamWriter(OutputStream out,String charset) : 使用指定的字符编码创建OutputStreamWriter对象

将字符串写入文件后读出


import java.io.*;

public class Demo01 {
    public static void main(String[] args) throws IOException {
        // 创建目标文件路径
        String src = "IO\\a.txt";
        // 创建输出流
        Writer writer = new OutputStreamWriter(new FileOutputStream(src));
        // 创建输入流对象
        Reader reader = new InputStreamReader(new FileInputStream(src));
        // 具体操作
        writer.write("你好,中国!");
        writer.flush();  // 这个必须要有,否则会造成IO阻塞,导致reader读取不成功
        char[] chars = new char[1024];
        int len;
        while ((len = reader.read(chars)) != -1) {
            System.out.println(new String(chars, 0, len));
        }
        // 关闭资源
        reader.close();
        writer.close();
    }
}


字符流



字符输入流和字符输出流


概述:

FileReader:字符输入流,其父类是转换输入流,顶层父类是Reader,拥有Reader抽象类中的所有方法;

FileWriter:字符输出流,其父类是转换输出流,顶层父类是Writer,拥有Writer抽象类中的所有方法;


构造方法:

// FileReader构造方法
FileReader(String fileName)		// 通过文件路径创建字符输入流对象
FileReader(File file)			// 通过文件对象创建字符输入流对象
// FileWriter构造方法
FileWriter(String fileName)		// 通过文件路径创建字符流输出流对象
FileWriter(File file)			// 通过文件对象创建字符流输出流对象

字符流和转换流的区别:

  1. 构造方法参数不同:转换流构造方法传入的是字节流,字符流构造方法传入的是文件的路径或文件的对象;
  2. 转换流可以指定编码去读和写,而字符流只能使用平台默认的编码去读和写;

代码示例:

import java.io.*;

public class Demo04 {
    public static void main(String[] args) throws IOException {
        // 创建源文件路径
        String source = "IO\\a.txt";
        // 创建目标文件路径
        String target = "IO\\b.txt";
        // 创建输入流对象
        Reader reader = new FileReader(source);
        // 创建输出流对象
        Writer writer = new FileWriter(target);
        // 具体操作
        char[] chars = new char[1024];
        int len;
        while ((len = reader.read(chars)) != -1) {
            writer.write(new String(chars, 0, len));
        }
        // 释放资源
        writer.close();
        reader.close();
    }
}

字符缓冲流


概述:

字符缓冲流分为字符缓冲输入流和字符缓冲输出流,其和字节缓冲流类似,其提供一个默认长度为8192的字符数组;它们拥有Writer和Reader中的所有方法,与此同时还有自己特有的新方法;

BufferedWriter

  1. 构造方法:

    BufferedWriter(Writer out) // 创建字符缓冲输出流对象
    
  2. 特有方法:

    void newLine() // 写一行行分隔符,行分隔符字符串由系统属性定义
    

BufferedReader

  1. 构造方法:

    BufferedReader(Reader in) // 创建字符缓冲输入流对象
    
  2. 特有方法:

    String readLine() // 读一行文字。 结果包含行的内容的字符串,不包括任何行终止字符如果流的结尾已经到达,则为null,不能读取换行符号
    

字符缓冲流复制文件:

import java.io.*;

public class Demo07 {
    public static void main(String[] args) throws IOException {
        // 创建源文件路径
        String source = "IO\\a.txt";
        // 创建目标文件路径
        String target = "IO\\b.txt";
        // 创建字符缓冲输入流对象
        BufferedReader br = new BufferedReader(new FileReader(source));
        // 创建字符缓冲输出流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter(target));
        // 具体操作
        String line;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        // 释放资源
        bw.close();
        br.close();
    }
}

发布了22 篇原创文章 · 获赞 0 · 访问量 350

猜你喜欢

转载自blog.csdn.net/Yi__Ying/article/details/103840344