本文从为什么发明转换流,什么时候用转换流这个角度来解释
博主在学习io流的时候就对这两个点疑惑,如果你也这样可以跟随我的视角来理解
转换流的作用 (字面意思:字节流和字符流的转换)
- 解码过程:字节流→指定编码→字符流
- 编码过程:字符流→指定编码→字节流
代码案例
- 功能1:指定一定的编码格式来进行读取和写入
- 示例一:将一个GBK的本地文件转换成(UTF-8)文件
1:用普通字符流操作代码:
Filefile=newFile("D:\\包\\gbk.txt");Filefile1=newFile("D:\\包\\utf-8.txt");//Java 中 FileReader 和 FileWriter 是简化版字符流,不支持直接指定编码(这两个类会使用系统默认编码,无法手动传编码参数)!FileReaderfi=newFileReader(file);FileWriterfr=newFileWriter(file1);intb;while((b=fi.read())!=-1){fr.write((char)b);}fr.close();fi.close();用普通字符流FileReader/FileWriter的结果出现乱码:
乱码原因:普通流只能按系统默认的编码格式来进行读取和写入不能指定格式,也就是他读取和写入的编码方式一样的,注定会乱码。
用普通字节流
FileInputStream/FileOutputStream是可以完成这个功能的,并且不乱码,这因为字节流和字符流的核心区别就是字节流仅处理「原始字节(8 位二进制数据)」,不涉及任何字符编码转换;而「编码方式」是字符流(Character Stream)特有的概念,本文为了理解转换流的功能所以才将普通字符流来和转换流(也是字符流)来进行对比。
1:用普通字符流操作代码:
//创建数据源Filefile=newFile("D:\\包\\gbk.txt");Filefile1=newFile("D:\\包\\utf-8.txt");//创建管道流FileInputStreamfi=newFileInputStream(file);FileOutputStreamfo=newFileOutputStream(file1);//要指定编码读取 / 写入,用 InputStreamReader(基于字节流 + 编码)和 OutputStreamWriter 替代。InputStreamReaderisr=newInputStreamReader(fi,"GBK");OutputStreamWriterosw=newOutputStreamWriter(fo,"UTF-8");//开始读写操作intb;while((b=isr.read())!=-1){osw.write((char)b);}//关闭资源osw.close();isr.close();用转换流(高级字符流)InputStreamReader/OutputStreamWriter的结果:
- 功能2:就是利用字节流读取和输出,但是还想用字符缓冲流的方法(
readLine()/newLine()),字节缓冲流并没有这俩功能 - 示例二:用字节流做基础流但是使用字符缓冲流的功能
代码演示:
//创建数据源Filefile=newFile("D:\\包\\学生信1息.txt");Filefile1=newFile("D:\\包\\学生信息.txt");//创建管道流FileInputStreamfi=newFileInputStream(file);FileOutputStreamfo=newFileOutputStream(file1);//字节流(如 FileInputStream/FileOutputStream)的核心行为是://读取阶段:从源文件中逐个 / 批量读取二进制字节(比如 GBK 编码的 “中” 是D6 D0两个字节,UTF-8 的 “中” 是E4 B8 AD三个字节),完全不关心这些字节对应什么字符;//写入阶段:把读取到的二进制字节原封不动写入目标文件,字节的顺序、值都没有任何修改。//整个过程就像 “复制粘贴文件的二进制底层数据”—— 源文件的编码是 GBK/UTF-8/GB2312 都无所谓,字节流只负责 “搬字节”,不解析、不转换,目标文件的字节和源文件 100% 一致,自然不会乱码。InputStreamReaderisr=newInputStreamReader(fi);OutputStreamWriterosw=newOutputStreamWriter(fo);BufferedReaderbr=newBufferedReader(isr);BufferedWriterbw=newBufferedWriter(osw);//开始读写操作Stringstr;while((str=br.readLine())!=null){bw.write(str);bw.newLine();//写完一行,换行}//关闭资源bw.close();br.close();