黑马训练营---------字节流缓冲区原理讲解

来源:互联网 发布:北大青鸟软件测试专业 编辑:程序博客网 时间:2024/06/02 16:52
---------------------- ASP.Net+Android+IO开发S、.Net培训、期待与您交流! ----------------------

/*自定义字节流缓冲区,原理:先利用FileInputStream的read方法从硬盘中一个个的读取数据存入到内存中定义的数组中,
然后在利用BufferedInputStream的read方法从字节数组中一个一个的往外读:
 为什么在BufferedReader 中模拟缓冲区用Buffered,而这里用字节数组。
*/
public  class MyBufferedStream extends InputStream {

 private InputStream f;
 private byte[] by=new byte[1024];
 private int count=0,pos=0;
 public MyBufferedStream(InputStream f){
  this.f=f;
 }
 public int myRead()throws IOException {/*这个地方为什么要用int来接收。如果按照Byte来接收,就有可能会出现连续读到8个1也就是-1
 ,这时候就与结束符-1矛盾,就会出现不能够读完整,把接接收类型改为int类型后,8个一位的-1就变成了32位,并在提升的过程我们&上了255(8个1)
 ,这样即能够保证最低8为数据的原样,避免了伪结束-1.
 */
  if(count==0){
   count=f.read(by);
   if(count<0)
    return -1;
   pos=0;
   byte b=by[pos];
   pos++;
   count--;
   return b&255;//为什么需要与上255。(返回类型为Int)
  }
  else if(count>0){
   byte b=by[pos];
   pos++;
   count--;
   return b&0XFF;
  }
  return -1;
 }
 public void myClose()throws IOException{//向外提供一个关闭流的方法。
  f.close();
 }

 @Override
 public int read() throws IOException {
  // TODO Auto-generated method stub
  return 0;
 }
}
class DemoBuffered
{
 public static void main(String[] args)throws IOException{
  FileInputStream fr=new FileInputStream("SystemIO\\copy1.mp3");
  MyBufferedStream mbs=new MyBufferedStream(fr);
  FileOutputStream fos=new FileOutputStream("SystemIO\\copy3.mp3");
  int b=0;
  long start=System.currentTimeMillis();
  while(( b=mbs.myRead())!=-1){
   fos.write(b);
  }
  mbs.myClose();
  fos.close();
  long end=System.currentTimeMillis();
  System.out.println(end-start);
 }
}
/*
 * 一个int是4个8位,byte是一个8位。
 *
11111111-111111110000000000101001001010100101010010101001010


byte: -1  --->  int : -1;
00000000 00000000 00000000 11111111  255

11111111 11111111 11111111 11111111


11111111  -->提升了一个int类型 那不还是-1吗?是-1的原因是因为在8个1前面补的是1导致的。
那么我只要在前面补0,即可以保留原字节数据不变,又可以避免-1的出现。
怎么补0呢?

 11111111 11111111 11111111 11111111                       
&00000000 00000000 00000000 11111111
------------------------------------
 00000000 00000000 00000000 11111111

0000-0001
1111-1110
000000001
1111-1111  -1


结论:
字节流的读一个字节的read方法为什么返回值类型不是byte,而是int。
因为有可能会读到连续8个二进制1的情况,8个二进制1对应的十进制是-1.
那么就会数据还没有读完,就结束的情况。因为我们判断读取结束是通过结尾标记-1来确定的。
所以,为了避免这种情况将读到的字节进行int类型的提升。
并在保留原字节数据的情况前面了补了24个0,变成了int类型的数值。


而在写入数据时,只写该int类型数据的最低8位。


*/

---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------