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("中国\r\n".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。
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步