为什么会出现字符流?
  由于字节流操作中文不是特别的方便,所以Java就提供字符流
  字符流 = 字节流 + 编码表
  用字节流复制文本文件时,文本文件也会有中文,但是没有问题,原因是最终底层操作会自动进行字节拼接成中文,如何识别是中文的呢?
  汉字在存储的时候,无论选择哪种编码存储,第一个字节都是负数

什么是字符集?
是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等,计算机要准确的存储和识别各种字符集符号,就需要进行字符编码,一套字符集必然至少有一套字符编码。常见字符集有ASCII字符集、GBXXX字符集、Unicode字符集等
ASCII字符集:
  ASCII:是基于拉丁字母的一套电脑编码系统,用于显示现代英语,主要包括控制字符(回车键、退格、换行键等)和可显示字符(英文大小写字符、阿拉伯数字和西文符号)基本的ASCII字符集,使用7位表示一个字符共128字符。ASCII的扩展字符集使用8位表示一个字符,共256字符,方便支持欧洲常用字符。是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等
GBXXX字符集:
  GBK:最常用的中文码表。是在GB2312标准基础上的扩展规范,使用了双字节编码方案,共收录了21003个汉字,完全兼容GB2312标准,同时支持繁体汉字以及日韩汉字等
Unicode字符集:
  UTF-8编码:可以用来表示Unicode标准中任意字符,它是电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码。互联网工程工作小组(IETF)要求所有互联网协议都必须支持UTF-8编码。它使用一至四个字节为每个字符编码
编码规则:
128个US-ASCII字符,只需一个字节编码
拉丁文等字符,需要二个字节编码
大部分常用字(含中文),使用三个字节编码
其他极少使用的Unicode辅助字符,使用四字节编码

 测试不同字字符集下"中国"两个字的编码

    public static void main(String[] args) throws Exception {
        //定义一个字符串
        String s = "中国";
        byte[] a = s.getBytes(); //[-28, -72, -83, -27, -101, -67]
        byte[] UTF8 = s.getBytes("UTF-8"); //[-28, -72, -83, -27, -101, -67]
        byte[] GBK = s.getBytes("GBK"); //[-42, -48, -71, -6]
        System.out.println(Arrays.toString(a));
        System.out.println(Arrays.toString(UTF8));
        System.out.println(Arrays.toString(GBK));

        String s1 = new String(a);
        String s2 = new String(UTF8,"UTF-8");
        String s3 = new String(GBK,"GBK");
        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);
    }

输出:

[-28, -72, -83, -27, -101, -67]
[-28, -72, -83, -27, -101, -67]
[-42, -48, -71, -6]
中国
中国
中国

 

InputStreamReader:是从字节流到字符流的桥梁,它读取字节,并使用指定的编码将其解码为字符,它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集
OutputStreamWriter:是从字符流到字节流的桥梁,使用指定的编码将写入的字符编码为字节,它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集

 

字符流写数据的5种方式

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)     写一个字符串的一部分

(注意,执行需要 flush() 刷新)

  public static void main(String[] args) throws Exception{
        OutputStreamWriter outputStreamWriter=new OutputStreamWriter(new FileOutputStream(".\\src\\hello.txt"));
        outputStreamWriter.write(97); //写一个字符
        outputStreamWriter.flush();

        char[] chs = {'a', 'b', 'c', 'd', 'e'};
        outputStreamWriter.write(chs);  //写一个字符数组
        outputStreamWriter.flush();

        outputStreamWriter.write(chs, 0, chs.length);  //写字符数组的一部分
        outputStreamWriter.write(chs, 1, 3);
        outputStreamWriter.flush();

        outputStreamWriter.write("我是中国人");  //写一个字符串
        outputStreamWriter.flush();

        String s="我是中国人";
        outputStreamWriter.write(s,1,s.length()-1); //写一个字符串的一部分
        outputStreamWriter.flush();

        outputStreamWriter.close();
    }

 

 

字符流读数据的2种方式

int read()       一次读一个字符数据
int read(char[] cbuf)      一次读一个字符数组数据

public static void main(String[] args) throws Exception{
        InputStreamReader inputStreamReader=new InputStreamReader(new FileInputStream(".\\src\\hello.txt"));

        int a;
        while((a=inputStreamReader.read())!=-1){    // 一次读取一个字符数据
            System.out.print((char) a);
        }

        char[] b=new char[1024];
        int len;
        while ((len=inputStreamReader.read(b))!=-1){       //一次读取一个字符数组
     System.out.println(new String(b,0,len)); 
   }  
    inputStreamReader.close();
}

 

 

字符流复制文件(InputStreamReader和OutputStreamWirter

        InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(".\\src\\hello.txt"));
        OutputStreamWriter outputStreamWriter= new OutputStreamWriter(new FileOutputStream(".\\src\\helloCopy.txt"));

        char[] chs = new char[1024];
        int len;
        while ((len = inputStreamReader.read(chs)) != -1) {
           outputStreamWriter.write(chs, 0, len);
        }

        outputStreamWriter.close();
        inputStreamReader.close();
    }

 

字符流复制文件(FileReader和FileWirter

    public static void main(String[] args) throws IOException {
        FileReader fileReader = new FileReader(".\\src\\hello.txt");
        FileWriter fileWriter = new FileWriter(".\\src\\helloCopy.txt");

        char[] chs = new char[1024];
        int len;
        while ((len = fileReader.read(chs)) != -1) {
            fileWriter.write(chs, 0, len);
        }
        fileReader.close();
        fileWriter.close();
    }

 总结:InputStreamReader 是用来读取原始字节流,可指定编码格式,而FileReader是读取字符流,使用系统默认的编码格式,当读取中文文件易出现乱码问题。

 

posted on 2021-12-25 14:34  之火  阅读(145)  评论(0)    收藏  举报