【Java】Java IO之字节流与字符流

Java IO(一) 字节流与字符流

在日常写代码中,用到文件读取时会看到各种XXXInputStream、XXXOutputStream类,Java的基本IO流名字命名都是这样一种形式,以至于很容易将IO类混淆,很难记住其中的区别,笔者将对Java IO中的类进行区别分析。首先从字节流和字符流的区别开始讲起。

字节流和字符流的区别

  • 字节流是用于读写字节数据的(比如图像、视频数据)

  • 字符流是用于读写字符数据的,字符数据也就是我们能看懂的文本数据,事实上字符在文件中也是以字节形式存储,字节数据需要进行字符集的转换才能以字符的形式呈现。字符流就是用于直接读取字符数据的,虽说时直接读取字符数据,但其过程还是:读取字节数据 → 字符集转码 → 字符 这样一个过程,只是Java将整个过程封装了便于直接读取字符数据,有兴趣的可以看源码,字符流对象里是创建了字节流对象的,比如FileReader里有个构造函数如下:

public FileReader(File file) throws FileNotFoundException {
	super(new FileInputStream(file));
}

接下来通过代码进行一些分析:

import java.io.*;

/**
 * 测试以字节流和字符流方式读取中英文的结果
 * 结果表明字节流读取会使读取出来的中文内容乱码,而英文不会
 * (每次读取一个字节也不会造成英文乱码,顺便验证了在文件中一个字符占用一个字节)
 * 而字符流读取不会出现中文乱码情况
 */
public class ByteStreamAndCharStream {

    public static void main(String[] args) throws IOException {
        // readByteStream1();
        // readByteStream2();
        readCharStream();
    }

    /**
     * 以字节流方式读取文件,一次读取一个字节
     * @throws IOException
     */
    public static void readByteStream1() throws IOException {
        File file = new File("testInput");
        // 字节输入流对象,指定数据源为file对象
        FileInputStream fis = new FileInputStream(file);

        int ch = 0;

        while ((ch = fis.read()) != -1){
            System.out.print((char)ch);
        }
        System.out.println();
    }

    /**
     * 以字节流方式读取文件,一次读取多个字节
     * @throws IOException
     */
    public static void readByteStream2() throws IOException {
        File file = new File("testInput");
        // 字节输入流对象,指定数据源为file对象
        FileInputStream fis = new FileInputStream(file);

        // byte[] buf = new byte[100]; 尝试将buf的大小减小,可以发现中间出现更多的乱码,
        // 因为每次只读取1024个byte,出现一些字符恰好被截断的情况
        byte[] buf = new byte[1024];
        int len = 0;

        while ((len = fis.read(buf)) != -1){
            System.out.print(new String(buf,0,len));
        }
        System.out.println();
    }

    /**
     * 以字符流方式读取文件,一次读取一个字符
     * 读取多个字符使用read(char[]),结果一样,可自行实验
     * @throws IOException
     */
    public static void readCharStream() throws IOException {
        File file = new File("testInput");
        FileReader fr = new FileReader(file);

        int ch = 0;

        while ((ch = fr.read()) != -1){
            System.out.print((char)ch);
        }
    }
}

这段代码的测试文件中包含中文和英文,三个方法的测试结果分别为

  • readByteStream1方法:中文全部乱码,英文未出现乱码,原因是一个中文汉字在文件中占用两个字节而英文字母占用一个字节,一次读取一个字节会使每个中文字符截断,造成乱码
  • readByteStream2方法:中文部分乱码,每次读取字节的长度越小,出现的乱码越多,原因是字符串被拆分为多个部分,每个部分的连接处可能会出现字符截断,在该这个连接处就出现乱码,每次读取长度越小,截断字符越多
  • readCharStream方法:中文和英文都没有出现乱码,因为FileReader是一次读取一个字符。

以上就是字节流和字符流方式读取文件的区别,读者可运行以上代码观察测试结果。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章