黑马程序员技术交流社区
标题:
介绍一下字节流里面的read()和Write()方法的简单实现原理,
[打印本页]
作者:
朱永志
时间:
2014-1-14 10:19
标题:
介绍一下字节流里面的read()和Write()方法的简单实现原理,
看了毕向东的IO流部分的字节流,自定义一个缓冲区,并且自定义以各read()方法,涉及到将byte转换成int向上转型,-1为什么要与上255呢?
作者:
tuanjie
时间:
2014-1-14 10:33
import java.io.IOException;
import java.io.InputStream;
/**
* 自定义字节缓冲流 简单模拟实现BufferedInputStream中的read()方法
* */
public class MyBufferedInputStream {
//持有一个InputStream对象实例
private InputStream in;
//定义一个字节数组,用于暂时缓存读取的数据
private byte[] buf = new byte[1024*4];
//定义一个指针
int pos = 0;
//定义计数器
int count = 0;
public MyBufferedInputStream(InputStream in){
this.in = in;
}
//定义一个myRead()方法,简单模拟实现BufferedInputStream中的read()方法
public int myRead() throws IOException{
//如果计数器(字节数组的数据大小)为0,说明字节数组为空,没有数据,需要从硬盘上读取数据
if(count == 0){
count = in.read(buf);
//如果硬盘上的数据已经全部读取完
if(count < 0){
return -1;
}
//每次从硬盘上重新读取数据存储到字节数组中后都将指针重置
pos = 0;
//获取字节数组中的第一个字节数据
byte b = buf[pos];
//计数器减一
count--;
//指针后移一位
pos++;
//返回数据
return b&255; //此次详解见下面(1)
}else if(count > 0){
byte b = buf[pos];
//计数器减一
count--;
//指针后移一位
pos++;
//返回数据
return b&255; //此次详解见下面(1)
}
return -1;
}
//定义一个关闭流的方法,用于模拟BufferedInputStream中的close()方法
public void close() throws IOException{
in.close();
}
}
/*(1):读取字节数组中的数据都是byte类型,而最后返回值类型却是int类型,是将byte类型数据自动转换成int类型,是为了避免读取到的一个字节类型,其八位都是1的情况,
1个byte类型的数据,其八位都是1,意味着该字节的值为-1,转换int类型后也是-1,就会因为返回值是-1而误认为文件数据已经读取完。
byte b = buf[pos]; b是byte类型,占八位,如果1个字节八位都是1,即11111111,转换成int类型,即十进制就是-1
如:byte -1 --->二进制是 11111111
int -1 -----> 二进制是 11111111-11111111-11111111-11111111
byte类型的 -1(11111111) 提升为int类型,结果还是-1 ,由于int类型是32位,byte的-1转换为int类型的-1时,自动在byte类型-1的8个1前面全补1,这就导致了byte类型的-1转换为int类型的,结果还是-1.为了避免读取的字节数据八位都是1,再转换为int类型时结果还是-1的情况,可以在byte类型的的八位1前面都补0,即:
byte -1 --->二进制是 11111111 转换int类型在八个1前面都补0,得到 00000000-00000000-00000000-11111111 (其十进制的值为255)。这样既可以保持原字节数据不变,而又避免了-1的情况。
让byte -1 --->二进制是 11111111 转换为int类型时,八个1前面都补0,可以通过
11111111-11111111-11111111-11111111
& 00000000-00000000-00000000-11111111 (255)
---------------------------------------------------------------
00000000-00000000-00000000-11111111
这种方式实现,也就是代码中的 b&255;
而通过 b&255这种方式读取一个字节数据,返回一个int类型数据,即4个字节数据,那样的话,返回的数据应该是读取的数据的4倍,如果这样的话,将读取的数据写到另一个文件中时,就会出现写入的文件大小是读取文件大小的4倍,但是,事实上,读取的数据和返回的数据大小都是一样的,读取的文件大小和写入的文件大小都是一样的,那是应为read()方法读取数据时将byte类型提升为int类型,而写入数据时,write()方法也是写入字节数据,会将int类型强制转换为byte类型,即将int类型的最后八位写入到byte中,其他的都抛弃掉。
wirte()方法写入数据时:
int 类型 ------------------------------------------------------------------------------>byte
00000000-00000000-00000000-111111111 ------------------------------->11111111(只要后八位,前24位抛弃掉)*/
复制代码
作者:
汪伟楠
时间:
2014-1-14 10:42
read:向上提升,write强制转换,两者保证原数据的不变化;
read方法返回的不是byte类型的字节而是int类型的原因是:避免了-1的发生,而write方法再将最低的一个字节写出去,保证了原数据的原样性。
byte-1提升了一个int类型,还是-1的原因:因为8个1前面补的是1导致的,那么只要在前面补0即可以保留原字节数据不变,又可以避免-1的出现,所以&255;
简单来说就是:在用输入流读取一个byte数据时,有时会出现连续8个1的情况,这个值在计算机内部表示-1,正好符合了流结束标记。所以为了避免流操作数据提前结束,将读到的字节进行int类型的扩展。保留该字节数据的同时,前面都补0,避免出现-1的情况。
作者:
朱永志
时间:
2014-1-14 10:48
{:soso_e142:}欧拉,谢谢楼上的介绍。
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2