前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >IO流 秦始皇与编码的故事

IO流 秦始皇与编码的故事

作者头像
用户5745563
发布2019-07-04 11:42:21
5700
发布2019-07-04 11:42:21
举报
文章被收录于专栏:码思客码思客
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种类的使用方法。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-02-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码思客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档