正所谓怕什么来什么,这是知名的“墨菲定律”。Java基础涵盖各个方面,敢说Java基础扎实的人不是刚毕业的学生,就是工作N年的程序员。工作N年的程序员甚至也不敢人人都说Java基础扎实,甚至精通,往往只是“无他唯熟尔”——熟手而已。

  IO这块我确实怕,它不难,只有两个方面:输入/输出。但你说它用得多不多,我相信没有你写的并发多,并发往往是处处可见,写着写着就熟了,而IO却往往只是某个模块会涉及,所以也就并不是每个程序员在开发维护自己的模块时都会用到有关IO的API,而碰到的时候常常陷入窘迫,不知道怎么写。

  我想研究IO这块愿意正是想巩固自己的Java基础,并希望能成为精通Java的那个人。 本文作为Java IO系列的开篇,首先要介绍几个概念:字节与字符。原因在于,Java IO的API分为字节流和字符流,了解什么是字节和字符有助于我们后续IO的理解。

字节(Byte)

  计算机中存储数据的一个单位。比它小的是位(bit,也叫比特),这是在计算机中数据存储的最小计量单位,1位存放的是二进制的数据0和1,如下所示。

  当然比字节更大的是KB(千字节),1KB = 1024B,再到后面就是MB(兆字节),1MB = 1024KB,GB、TB……

  Java中有用于表示字节的数据类型——byte,再次不妨回顾下有关在Java中有关byte的一些知识。

  前面提到1个字节等于8个二进制位,那么也就是说1个字节能表示的最大数为[0, 255](闭区间),但是,在Java中byte类型是有符号型的,也就是说在它的最高位是符号位。也就是说除去最高位符号位,还剩下7个二进制位,那么7个二进制所能表示的最大数为[0, 127],这是正数,加上最高位为1表示负数时,byte型数据类型所能表示的最大数为[-127, 0],也就是说byte型的数据范围是[-127, 127],真的是这样吗?错了。上面的分析是错误的。Java中byte型数据类型的取值范围为[-128, 127]。

  错误的原因是没有考虑到计算机中数值存储的编码问题。所以这又会继续延伸到原码、反码、补码的概念。

  • 原码:最高位表示符号位,0表示正数,1表示负数,其余位表示真实数值。前面的错误分析正是将计算机中数值存储定义为了原码,所以才会得到Java中byte型数据类型的取值范围是[-127, 127]。
  • 反码:同样最高位表示符号位,正数的反码与原码相同,而负数的反码除符号位外,其余位取反。
  • 补码:同样最高位表示符号位,正数的反码与原码相同,而负数的补码除符号位外,其余位取反+1。计算机中数值的存储正是补码。

  可以通过程序来观察体会,计算机中数值存储是通过补码来存储的。

System.out.println("正数3的二进制原码为:11,其补码与原码相同为:" + Integer.toBinaryString(3));
System.out.println("负数-3的二进制原码为:111,其补码与为(int型占4bytes=32bits,只看最后的3位):" + Integer.toBinaryString(-3) + "(不信将最后三位补码-1取反得到原码)");

  通过运算结果可以看到,计算机中的数值确实是以补码方式存储的。

  在了解了原码、反码、补码,以及知道计算机中数值是以补码方式存储过后,现在回到Java中byte型数据类型的范围上来。就算是以补码方式的存储,可以确定的是在byte型数组中正数(最高位为0)的范围是[0, 127]一共128个数,那么负数(最高位为1)的原码范围则是[-127, -0],二进制也就是[11111111, 10000000],注意这是原码,并且这个地方有点冲突,也就是出现了-0这种表示,这显然是不合理的或者说0已经在正数中已经包括了,在这里实际上byte型数组做了一定的处理,也就是把把-0的补码当做了-128,-0的原码是10000000,它的反码则是11111111,它的补码则还是10000000,反码+1过后需要进位,但是最高位表示符号位,所以被挤掉了,总之此时负数的范围则是[-128, 0),byte型数组的范围则是[-128, 127]。原因是由于-0和0表示的都是0为避免浪费,将-0表示为-128扩大了范围。

  这一段我们通过字节(Byte)这种表示计算机数据存储的单位,延伸了Java中byte型数据类型的取值范围,进而回顾了计算机中数值存储的编码方式,应该是能更好的理解字节这个概念。下面将介绍什么又是字符。

字符(Char)

  字符表示文字和符号。人与人之间通过人类语言进行沟通,计算机通过二进制来进行沟通,当人-计算机-人,中间多了计算机的媒介过后,中间就需要计算机对我们人类的语言符号“编码”进行传输,而计算机-人这个过程又称之为“解码”。这有点类似“加密”“解密”的过程。

  在计算机刚出现的时候只能传输英文字符,这里的传输包括是显示和存储,前面提到要进行编码存储,既然要编码就需要一张表来表示A是什么,B是什么,就好比摩斯密码中的密码本一样。那时的“码表”也就是编码方式叫做ASCII。

  

  计算机继续在发展,需要发展到其他国家和地区,此时就需要对汉字、日文、韩文等进行编码,但原有的ASCII肯定不能满足,它的设计是包括了英文和符号,此时就出现了ANSI编码(也叫做ASCII扩展),这实际上是一种规范,一种本地化的规范编码,例如在中文操作系统中ANSI代表的就是GB2312编码(当然也有它的扩展叫做GBK编码),在日文操作系统中ANSI代表的就是JIS等等。ANSI编码采用2个字节来表示一个字符(范围在0x80-0xFF),两个字节也就是16个二进制位,理论上可以表示216个字符,当然这需要减去0x00-0x79这个范围,这就能表示很多很多的字符了。GB2312编码也就才表示了6000多个常用汉字。不过这种编码方式还是带来了新的问题,这只是做了本地化,也就是说在GB2312的编码环境下,无法对日文进行编码。所以还需要做国际化。

  随着计算机的继续发展,国际化越来越重要这当然也就包括编码方式的改变,为避免ANSI不兼容的状况,又制定了新的编码规则——UNICODE。在Java中使用的就是UNICODE编码,这符合Java跨平台的特性,这也就解释了Java中char字符的数据类型占用的是2个字节,因为Java使用UNICODE编码,而UNICODE是2个字节表示1个字符。UNICODE解决了不同语言在不同平台不兼容的情况,但也有一个小小的弊端,也就是稍微比前面两种要占空间,以UNICODE字符集在内存中存储的字符串我们称之为为“宽字节字符串”,实际上之后对于字符编码的工作就集中在了如何缩短字节空间上。 这里就着重介绍UNICODE编码,UNICODE编码之所以略占空间,是因为它使用2个字节来表示1个字符。就算是英文也是使用2个字节。而ACSII和ANSI则使用1个字节表示英文。空间的占用就体现在了这个地方,如下图所示。

  可以看出,这就白白地浪费掉了1个字节的空间,在这里实际上又可以继续延伸出有关计算机基础的知识,也就是在计算机中的数据在内存中的存储方式是大端模式(Big-Endian,也称高字节在前),还是小端模式(Little-Endian,也称低字节在前)。所谓大端模式就是高位字节在内存的低地址端,低位字节在内存的高地址端。而小端模式则是高位字节在内存的高地址端,低位字节在内存的低地址端。上图所示方式就是大端模式,可以看到低位字节跑到了地址的左边也就是高地址端。需要清楚的是Java中采用的是大端模式。

  继续回到编码上来,由于UNICODE给任意字符都是采用的2个字节表示1个字符,会造成空间浪费,所以在UNICODE编码基础上,又出现了可变长编码的UTF-8编码,这种编码方式会灵活地进行字符的空间分配,不同字符所占用的内存空间不相同,在保证兼容性的同时,也保证了空间的最合理使用。

  这就是Java IO的基础知识,为的是便于后面Java IO中有关字节流和字符流的更好理解。

这是一个能给程序员加buff的公众号 

Java IO(1)基础知识——字节与字符的更多相关文章

  1. 第76节:Java中的基础知识

    第76节:Java中的基础知识 设置环境,安装操作系统,安装备份,就是镜像,jdk配置环境,eclipse下载解压即可使用,下载tomcat 折佣动态代理解决网站的字符集编码问题 使用request. ...

  2. 【Java面试】基础知识篇

    [Java面试]基础知识篇 Java基础知识总结,主要包括数据类型,string类,集合,线程,时间,正则,流,jdk5--8各个版本的新特性,等等.不足的地方,欢迎大家补充.源码分享见个人公告.Ja ...

  3. Java面试题-基础知识

    参考文章:Java面试题-基础知识 基础能力 什么是值传递和引用传递 线程状态有哪些,它们之间是如何转换的 进程与线程的区别,进程间如何通讯,线程间如何通讯? HashMap的数据结构是什么?如何实现 ...

  4. JAVA核心技术I---JAVA基础知识(工具类Arrays和Collections类)

    一:工具类 –不存储数据,而是在数据容器上,实现高效操作 • 排序 • 搜索 –Arrays类 –Collection类 二:Arrays类(处理数组) (一)基本方法 –排序:对数组排序, sort ...

  5. JAVA核心技术I---JAVA基础知识(static关键字)

    一:static特殊关键字用处 –变量 –方法 –类 –匿名方法 二:静态变量:类共有成员 –static变量只依赖于类存在(通过类即可访问),不依赖于对象实例存在. –所有的对象实例,对于静态变量都 ...

  6. Java JDBC的基础知识(三)

    在前面的Java JDBC的基础知识(二)和(三)中,主要介绍JDBC的原理和简单的应用过程.尤其在(二)中,可以发现代码进行多次try/catch,还有在前面创建连接等过程中好多参数我都给写定了. ...

  7. Java JDBC的基础知识(二)

    在我的上一篇Java JDBC的基础知识(一)中,最后演示的代码在关闭资源的时候,仅仅用了try/catch语句,这里是有很大的隐患的.在程序创建连接之后,如果不进行关闭,会消耗更多的资源.创建连接之 ...

  8. Java并发(基础知识)—— Executor框架及线程池

    在Java并发(基础知识)—— 创建.运行以及停止一个线程中讲解了两种创建线程的方式:直接继承Thread类以及实现Runnable接口并赋给Thread,这两种创建线程的方式在线程比较少的时候是没有 ...

  9. Java IO流基础总结

    前言 好久不用Java的IO流,把好多的基础知识都忘了,昨天在写一段代码,发现好多细节都忘了.那天在组织组内代码评审的时候,发现有人在乱用IO流相关的类,所以还是写篇文章,把这个知识点总结一下. IO ...

随机推荐

  1. Philosophy is systematic reflective thinking on life.

    1. perfect  coding 逻辑思维.抽象思维.发散思维 knowledge application                     design 2. Java Object: h ...

  2. CSS之 absoulte 属性

    特性: absoulte 与 float 具有相同的特性:包裹性,与破坏性  absoulte 与 float 可以交替使用  不受 relative 限制的 absoulte 定位,行为表现上可以不 ...

  3. 最佳时间买入卖出股票 Best Time to Buy and Sell Stock LeetCode

    LeetCode 我们有一个股票的数组,数组是每时间的钱,我们只能买入一次和卖出一次,求我们的最大收益. 我们知道了一个数组,那么我们可以在低价买入,然后高价卖出,但是需要知道我们的低价需要在高价之前 ...

  4. Python学习笔记(六)

    Python学习笔记(六) Ubuntu重置root密码 Ubuntu 16.4 目录结构 Ubuntu 命令讲解 1. Ubuntu重置root密码 启动系统,显示GRUB选择菜单(如果默认系统启动 ...

  5. C++点滴20130802

    1.sprintf与printf,fprintf为三兄弟.其中printf输出到屏幕,fprintf输出到文件,而sprintf输出到字符串中.通常情况下,屏幕是可以输出的,文件也可以写的(除非磁盘满 ...

  6. Java常用API

    常用Java API 一. java.io.BufferedReader类(用于从文件中读入一段字符:所属套件:java.io) 1. 构造函数BufferedReader(java.io.FileR ...

  7. 使用css3实现瀑布流布局效果

    使用CSS3可以轻松实现瀑布流布局,但这种方法有个缺点,就是对于商城类型的网站,价格筛选时,并不能达到理想效果. 1.column-count 把div中的文本分为多少列 2.column-width ...

  8. spring boot 自己输出json数据

    @RequestMapping("/json")public void json(HttpServletResponse response, Pager pager, TruckF ...

  9. IsoAlgo3d - A PCF 3D Viewer for Desktop, Tablet and Smart phone

    IsoAlgo3d - A PCF 3D Viewer for Desktop, Tablet and Smart phone eryar@163.com Abstract. IsoAlgo3d 通过 ...

  10. 【JAVA零基础入门系列】Day13 Java类的继承与多态

    继承是类的一个很重要的特性,什么?你连继承都不知道?你是想气死爸爸好继承爸爸的遗产吗?(滑稽) 开个玩笑,这里的继承跟我们现实生活的中继承还是有很大区别的,一个类可以继承另一个类,继承的内容包括属性跟 ...