| 
 复制代码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位抛弃掉)*/
 
 
 |