为什么InputStream.read()读取一个byte确返回一个int呢?
java 字节读取流的read方法一次读一个byte但返回int的原因
读取二进制数据按字节读取,每次读一个字节(byte)。
read()的底层是由C++实现的,返回的是unsigned byte,取值范围为[0~255],在java中没有对应的类型,所以只能用int类型接收,由Java接收得到的就是int[0、255]。
在java中byte只能表示[0-127]的无符号数。也对应这java中int[0-127]
那么[128-255]怎么表示?
在java中byte的范围是[-128,127],所以[128-255]只能由int来接收。
使用-128 & 0xff = 128
-127 & 0xff = 129
-1 & 0xff = 255
就把byte提升为int类型了,来表示数据。
---------------------------
在读取一个字节数据时,容易出现连续8个1的情况,连续8个1是-1, 正好符合了流结束标记。
所以要转换数据,将读到的字节进行int类型的提升。保留该字节数据的同时,前面都补0,避免-1的情况。
11111111------->0000 0000 1111 1111
-1 & 0xff = 255
因此java 字节读取流的read方法一次读一个byte就会返回int。
----------------------------
在使用字节输出流的write方法写入的时候,其实内部将int强转一下,还原成原来的byte字节数据。。
(byte)128 = -128
(byte)129 = -127
(byte)255 = -1
0000 0000 1111 1111--->1111 1111
-------------------------
举例这么说:
FileInputStream的read方法在做类型提升(将byte提升为int)
FileOutputStream的write的方法在做类型强转(将int强转为byte)
import java.io.*;
class MyBufferedInputStream
{
private InputStream in;
private byte[] buf = new byte[1024*4];
private int pos = 0;//用于操作数组元素的指针(索引,角标)。
private int count = 0;//记录住每一次往数组中存储的元素个数。
MyBufferedInputStream(InputStream in)
{
this.in = in;
}
/*
为什么,字节读取流的read方法一次读一个字节,返回值类型,不是byte,而是int呢?
那是因为,在读取一个字节数据时,容易出现连续8个1的情况,连续8个1是-1.
正好符合了流结束标记。所以为了避免,流操作数据是提前结束,
将读到的字节进行int类型的提升。保留该字节数据的同时,前面都补0.避免-1的情况。
*/
//一次读一个字节,从缓冲区(字节数组)获取。
public int myRead()throws IOException
{
//通过in对象读取硬盘上数据,并存储buf中。
if(count==0)
{
count = in.read(buf);
if(count<0)
return -1;
pos = 0;
byte b = buf[pos];
pos++;
count--;
return b&255;
}
else if(count>0)
{
byte b = buf[pos];
pos++;
count--;
return b&0xFF;
}
return -1;
}
public void myClose()throws IOException
{
in.close();
}
//=========调用以上类======
public static void copyMp3()throws IOException
{
MyBufferedInputStream bufis = new MyBufferedInputStream(new FileInputStream("c:\\0.mp3"));
BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("c:\\6.mp3"));
int temp = 0;
while((temp=bufis.myRead())!=-1)
{
bufos.write(temp);//输出流的write方法虽然接收是一个整数,四个字节,但是write只将最后一个字节写出。
//其他字节抛弃。
}
bufos.close();
bufis.myClose();
}
}
/*
结论:
字节流的读一个字节的read方法为什么返回值类型不是byte,而是int。
因为有可能会读到连续8个二进制1的情况,8个二进制1对应的十进制是-1.
那么就会数据还没有读完,就结束的情况。因为我们判断读取结束是通过结尾标记-1来确定的。
所以,为了避免这种情况将读到的字节进行int类型的提升。
并在保留原字节数据的情况前面了补了24个0,变成了int类型的数值。
而在写入数据时,只写该int类型数据的最低8位。
*/