美文网首页
IO流 秦始皇与编码的故事

IO流 秦始皇与编码的故事

作者: 码思客 | 来源:发表于2019-02-18 10:17 被阅读0次

    java零基础入门-高级特性篇(十一) IO 流 1

    IO的故事可以从2000多年前的始皇帝开始讲起。自从秦始皇统一六国以后,书同文,车同轨,统一货币度量衡,简单的说就是制定了一个统一的标准。而与本章有最大关系的就是“书同文”了。正是由于秦始皇统一了文字,所以今天不论是书籍还是网络,都有统一的文字标准,但是可惜的是,这个统一的标准只在国内是统一的。由于互联网将全世界的距离缩小到了你与屏幕的距离,这时候问题就出现了。

    编码的故事

    计算机是二进制的世界,而我们的世界却有着各种各样的语言,如果要将一篇文章存在计算机的硬盘上需要做什么?不仅仅是文章的保存,只要是需要借助计算机才能完成的工作,比如将一篇文章发到各个网站,或者通过通讯软件发给朋友,都会有一个过程,就是将人类语言转变为计算机的语言,这个过程就是编码。那么怎么将人类语言转为计算机语言呢?其实这个问题给你,你用不了多久就会想到办法。

    办法

    是不是这样?既然计算机只认识数字,把英文和数字对应起来不就可以了么。但是这里用的十进制,而计算机只认识二进制,那就将十进制换为二进制就可以 了。还有一个问题,其实除了英文字符,还有很多其他的符号,符号在计算机中也有很大的作用,按照这样的思路,第一代的编码规范 ASCII 编码就横空出世了。搞计算机的大佬个个都是天才,他们想的比你快,比你更全面。大佬掐指一算,符号加字母,128个不多不少刚刚好。为什么是128个?

    对照

    看看二进制的表示,0000 0000到0111 1111就是从0到127一共128个数,正好8位1字节(1个字节8位),正好一个字节全部搞定,大佬就是大佬。上图中是ASCII表中需要有印象的几个特殊字符。第一个是空字符,编号0,数字1编号49,大写字母A编号65,小写字母a编号97,最后一个表示delete。

    这个ASCII表是美国人发明的,所以表中只有字母和数字,因为对于美国人来说,这些就够了。但是欧洲人一看就发现问题了,光这几个字符不够用啊,比如念个电话号码比读一篇文章还难的法语,不练好舌头的震动就不会发音的德语,于是欧洲人弄了一套ISO-8859-1字符标准出来,满足了自己的需求。美国欧洲都有了自己的标准,我们也必须有自己的标准啊。中华文明博大精深,中文常用字就有几千个,加上不常用的怎么也得有几万,这怎么办?先把常用字弄出来,于是GB2312就出现了。后来为了完整的包含中文,将GB2312扩展了2次,第一次扩展后叫GBK,第二次扩展后叫GB18030。

    编码

    好了,看到不同的地区有自己的编码,各个国家玩的遍地开花,不弄个自己的标准都不好意思出门跟人家打招呼了,然后世界就乱了。美国人用ASCII编码发了个邮件给韩国人,韩国人用自己的编码打开一看,全是乱码,标准不同无法转换。怎么办?那就来个国际标准统一全世界呗,这就有了Unicode编码,有了Unicode,发邮件再也不乱码了。

    但是互联网的高速发展,希望有比Unicode更优秀的编码出现。因为Unicode包含了全世界所有的文字,那么它的范围肯定非常大,甚至需要4个字节来表示,但是如果是一篇美国人写的文章,用Unicode来编码,就会发生一个字节搞定的字符结果用了2个甚至4个字节来表示,浪费很多空间。

    最后,最重要的编码方式登场了,大家请记住他的名字 UTF-8。UTF-8继承了Unicode涵盖的所有字符,并且将长度变成了可变长。如果是美国人写的文章,用1个字节保存字符即可,如果是中国人的文章,用2个字节保存字符,并且都是UTF-8的编码方法,即节约空间,又统一编码。我们在web项目中使用最多的也就是UTF-8编码。

    下图是同一个文件分别用Unicode和UTF-8编码后的大小。可以发现使用UTF8编码的文件占用空间小了一半。

    不同编码

    最后用一个图来概括一下。

    总结

    看了上面这么多编码,真的是需要感谢始皇帝统一了中国,不然我们国内还有一堆编码,各种方言编码,那简直就是灾难啊。但是,这跟IO流有什么关系?

    IO流是什么

    首先明确一个知识点,计算机是二进制的世界,所以在计算机上存储的文件都是byte字节储存。而在计算机内,存储的文件可以分为两大类,一类是文字类型的文本,另外一类是各种媒体类型等,如果直接使用文本来打开这些文件,里面全是乱码,只有特定的软件才能打开。比如播放器打开视频文件,图片软件打开各种图片。

    针对这两种文件,java有两种IO流对应他们,那就是字节流和字符流。上面说过在互联网时代,使用UTF-8编码传输文件可以减小文件体积,加快传输速度,但是在计算机本地,使用Unicode编码较多,java虚拟机为了在全世界的机器上使用,所以它使用的是Unicode编码方式,而且是将字节转为字符,以方便支持各个国家的语言,所以如果要对文件进行编码使用字符流。如果不需要编码,则使用字节流,因为除了文字之外的文件,不需要我们看得懂他们的编码是什么,需要使用他们的时候有特定的软件对文件进行转码。

    文本打开图片

    用文本打开图片是上图的样子,这不是我们需要的,所以看图片使用图片软件即可。

    说了这么多,IO流到底是什么还是不懂,别急,这就说。

    首先看IO,IO对应Input/Output首字母,表示输入和输出。流又是什么呢?既然文件都是以字节存储,那么进行输入,输出的时候就是按照字节来传输,文件变成了一串数字,源源不断的从一个地方到另一个地方。比如复制文件的时候,经常会看到一个进度条,在这个进度条背后计算机在干什么呢?他在一边读文件,一边写文件,读的时候将文件用01011101的方式读出来,写入的时候,又将文件以01011101的方式写入到磁盘,看上去就像水流一样,源源不断。

    注意这里最小单位是字节,就是8位,比如01011101就是一个字节,最小的传输单位。

    复制文件

    文件传输完成之前,这个文件是打不开的,只有传输完成后,才是一个完整的文件,可以用软件打开。计算机内的文件传输,这就是IO流。除了计算机内部的传输,计算机还可以从远程服务器上通过网络读取文件,写入硬盘,这种方式也是通过IO流实现。

    java中的IO流

    java中的IO流体系比较庞大,涉及到很多类,但是常用的其实并不多,所以本文只会介绍最常用的部分。学会了常用的,其他的各位可以参考java的API,理解起来没有难度。下面来介绍一下java中的IO流体系。

    体系

    IO流主要分为两大类,一种是字符流,用来对文件进行编码,输出人类可以看懂的文字。另一种是字节流,用来传输各种软件可以识别的文件。每一大类都拥有输入和输出的功能,所有输入的字符流的父类叫做Reader,所有输出的字符流的父类叫做Writer。对应到字节流,所有输入的字节流的父类是InputStream,所有输出的字节流的父类是OutputStream。这几个父类按照分类和输入输出的功能来记忆会方便很多。

    以上四个类都是抽象类,为什么要使用抽象类?回忆一下前面的知识,抽象类用来定义子类的公共功能,还可以留下一部分抽象方法,到子类再来实现,这样不同的子类就可以有不同的功能了。比如上图右侧标识出了四种功能,分别是“带缓冲功能”,“字节与字符转换”,“字节操作文件”,“字符操作文件”,如果不使用抽象类,可能每一个类中都会有一堆重复的功能,也就是在抽象类中已经实现的功能,他们会重复的出现。而使用抽象类以后,每个子类只需要实现抽象类中的抽象方法即可。

    继续观察上图,会发现最终用来操作字符流的类是FileReader和FileWriter。如果需要缓冲功能,可以使用BufferedReader和BufferedWriter。而最终用来操作字节流的类是FileInputSteam和FileOutputStream,如果需要缓冲功能,则使用BufferedInputStream和BufferedOutputStream。发现没有,其实最终最重要的8个类就是字符和字节的输入和输出各一个,他们分别还有一个带缓冲功能的类,根据情况选择使用不同的类。

    下一章再来具体介绍上面8种类的使用方法。

    相关文章

      网友评论

          本文标题:IO流 秦始皇与编码的故事

          本文链接:https://www.haomeiwen.com/subject/ydkxrqtx.html