Java 编程下 IO 中的输入流的 read() 方法返回值为什么是 int 值(科普一下吧,某个大侠写的)

来源:互联网 发布:unity3d做好的小程序 编辑:程序博客网 时间:2024/06/01 10:29
 
 

sunzn:很基础的一个问题,估计很多程序员都没有仔细的想这个问题,放在这里利人利己吧!

Java 下 IO 中 FileReder 和 FileInputStream 分别是以字符和字节的形式来完成数据的读取的,然而返回值确是 int 类型的数据,这样做的核心目的只是要取到到一个 int 类型下的 -1 来表示数据流的末尾。为什么要这样做?又是怎么实现的呢?

 

首先看 FileReder :

FileReader fr = new FileReader("src.txt");
        int ch = fr.read();

如上面的代码,FileReader 的 read 方法返回值是一个 int 类型的变量来接收的,然而 read 方法在实际中却是以字符形式来进行数据的读取的。通过上面的基本数据类型的取值范围我们能发现 char 类型数据的取值范围为 0 ~ 65535 ,也就是说 char 类型数据是取不到负值的;int 类型数据的取值范围为 -2147483648 ~ 2147483647 ,可以取到负值;同时 int 的取值范围又包含 char 的取值范围,这就为使用 int 作为返回值类型提供了可能,因为流需要一个特殊的值来表示流末尾,这个值不应该在 char 的取值范围内,如果使用 char 取值范围内的值作为流末尾标志,那么这个值同样有可能出现在数据流中间作为数据来传输,流在读到这个值的时候会认为已经到达流末尾,后面未读取的数据将被截断。所以 Java 中选择了使用 -1 来作为流末尾,这个值不在 char 的取值范围内,所以不存在数据截断,然而 -1 又在 int 的取值范围内,同时 int 的取值范围包含 char 的取值范围,所以 FileReader 下 read 方法返回的 char 类型数据直接转为了 int 类型。

再看 FileInputStream :

FileInputStream fis = new FileInputStream("src.txt");
        int b = fis.read();

同理 FileInputStream 也需要一个自己取不到的值来作为流末尾的标志,Java 同样使用 -1 来作为字节流的流末尾,从上面基本数据类型的取值范围我们可以看到 byte 的取值范围为 -128 ~ 127 ,这就意味走着 byte 可以取到 -1 ,如果把 -1 直接当作 int 作为流末尾,那么就无法区分这个读到的结果是流末尾还是流中的数据了,那么 Java 是如何实现取值 -1 的呢?在 Java 内部,Java 通过高位补 0 来实现数据从 byte 到 int 的转换,举个例子:

-1 在 byte 类型和 int 类型中都可以取到,-1 在 byte 类型下的二进制存储形式为 11111111 ,然而使用 read 方法的时候,Java 内部将 byte 的高位补 0 将 byte 转为 int 类型,所以 byte 类型的 -1 在 int 类型下的二进制存储形式为 00000000 00000000 00000000 11111111,对应的 int 值为 255,通过高位补 0 ,所有 byte 类型的负数都转为了正数。然而在使用这些读到的 byte 数据时,只要将这些数据从 int 强转回 byte 即可得到原有的数据。所以就可以使用 -1 来作为流末尾的标志,因为 Java 内部将 byte 的负数通过高位补 0 将其转换为了负数。

原创粉丝点击