102.Java中IO流_字符流

字符流

计算机并不区分二进制文件与文本文件。所有的文件都是以二进制形式来存储的,因此,从本质上说,所有的文件都是二进制文件。所以字符流是建立在字节流之上的,它能够提供字符层次的编码和解码。例如,在写入一个字符时,Java虚拟机会将字符转为文件指定的编码(默认是系统默认编码),在读取字符时,再将文件指定的编码转化为字符。

常见的码表如下:

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

ISO8859-1:  拉丁码表。欧洲码表,用一个字节的8位表示。又称Latin-1(拉丁编码)或“西欧语言”。ASCII码是包含的仅仅是英文字母,并且没有完全占满256个编码位置,所以它以ASCII为基础,在空置的0xA0-0xFF的范围内,加入192个字母及符号,

藉以供使用变音符号的拉丁字母语言使用。从而支持德文,法文等。因而它依然是一个单字节编码,只是比ASCII更全面。

GB2312:  英文占一个字节,中文占两个字节.中国的中文编码表。

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

Unicode:  国际标准码规范,融合了多种文字。所有文字都用两个字节来表示,Java语言使用的就是unicode。

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

(我们以后接触最多的是iso8859-1、gbk、utf-8)

查看上述码表后,很显然中文的‘中’在iso8859-1中是没有对映的编码的。或者一个字符在2中码表中对应的编码不同,例如有一些字在不同的编码中是有交集的,例如bjg5 和gbk 中的汉字简体和繁体可能是一样的,就是有交集,但是在各自码表中的数字不一样。

例如

使用gbk 将中文保存在计算机中,

   中  国

对映  100  200   如果使用big5 打开

可能   ?  ...  

不同的编码对映的是不一样的。

很显然,我们使用什么样的编码写数据,就需要使用什么样的编码来对数据。

ISO8859-1:一个字节

GBK: 两个字节包含了英文字符和扩展的中文   ISO8859-1+中文字符

UTF-8 万国码,推行的。是1~3个字节不等长。英文存的是1个字节,中文存的是3个字节,是为了节省空间。

那么我们之前学习的流称之为字节流,以字节为单位进行操作之情的操作全是英文,如果想要操作中文呢?

测试:将指定位置的文件通过字节流读取到控制台

public class TestIo {
    public static void main(String[] args) throws IOException {
        String path = "c:\a.txt";
        writFileTest();
        readFileByInputStream(path);
    }

    private static void readFileByInputStream(String path) throws IOException {
        FileInputStream fis = new FileInputStream(path);

        int len = 0;
        while ((len = fis.read()) != -1) {
            System.out.print((char) len);
        }
    }

    private static void writFileTest() throws FileNotFoundException,
            IOException {
        // 创建文件对象
        File file = new File("c:\a.txt");
        // 创建文件输出流
        FileOutputStream fos = new FileOutputStream(file);
        fos.write("中国".getBytes());
        fos.close();
    }
}

发现控制台输出的信息:

???ú  是这样的东西,打开a.txt 文本发现汉字”中国”确实写入成功。

那么说明使用字节流处理中文有问题。

仔细分析,我们的FileInputStream输入流的read() 一次是读一个字节的,返回的是一个int显然进行了自动类型提升。那么我们来验证一下“中国”对应的字节是什么

使用:"中国".getBytes() 即可得到字符串对应的字节数组。是[-42, -48, -71, -6]

同样,将read方法返回值直接强转为byte ,发现结果也是-42, -48, -71, -6 。

代码:

public class TestIo {
    public static void main(String[] args) throws IOException {
        String path = "c:\a.txt";
        writFileTest();
        readFileByInputStream(path);
        //查看中国对应的编码
        System.out.println(Arrays.toString("中国".getBytes()));
    }

    private static void readFileByInputStream(String path) throws IOException {
        FileInputStream fis = new FileInputStream(path);
        int len = 0;
        while ((len = fis.read()) != -1) {
            System.out.println((byte)len);
        }
    }

    private static void writFileTest() throws FileNotFoundException,
            IOException {
        // 创建文件对象
        File file = new File("c:\a.txt");
        // 创建文件输出流
        FileOutputStream fos = new FileOutputStream(file);
        fos.write("中国
".getBytes());
        fos.close();
    }

}

那么中国 对应的是-42, -48, -71, -6是4个字节。 那就是一个中文占2个字节,(这个和编码是有关系的)

很显然,我们的中文就不能够再一个字节一个字节的读了。所以字节流处理字符信息时并不方便那么就出现了字符流。

字节流是 字符流是以字符为单位。

体验字符流:

public static void main(String[] args) throws IOException {
        
        String path = "c:\a.txt";
        readFileByReader(path);
    }
private static void readFileByReader(String path) throws IOException {
        FileReader fr = new FileReader(path);
        int len = 0;
        while ((len = fr.read()) != -1) {
            System.out.print((char) len);
        }
    }

总结:字符流就是:字节流 + 编码表,为了更便于操作文字数据。字符流的抽象基类:

Reader , Writer。

由这些类派生出来的子类名称都是以其父类名作为子类名的后缀,如FileReader、FileWriter。

author@nohert
原文地址:https://www.cnblogs.com/gzgBlog/p/13624611.html