Chinaunix首页 | 论坛 | 博客
  • 博客访问: 752912
  • 博文数量: 130
  • 博客积分: 2951
  • 博客等级: 少校
  • 技术积分: 1875
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-04 18:32
文章分类

全部博文(130)

文章存档

2013年(1)

2012年(129)

分类: Java

2012-03-29 19:51:17

ByteArrayInputStream和BufferedInputStream内部都维护着一个byte[]类型的数组,并且也都有mark(), reset(), skip()这样的方法,那么它们的区别是什么呢?通过看源码可以发现
1. 构造函数不同:
ByteArrayInputStream的构造函数

点击(此处)折叠或打开

  1. public ByteArrayInputStream(byte buf[]) {
  2.     this.buf = buf;
  3.         this.pos = 0;
  4.     this.count = buf.length;
  5.     }
可以看到,ByteArrayInputStream是用外来的一个byte []类型的数组来对内部的数组进行初始化,而之后的操作,如mark(), reset(), skip(), read()也都是建立在这个数组之上,这个数组的大小将不再能变化。

BufferedInputStream的构造函数:

点击(此处)折叠或打开

  1. public BufferedInputStream(InputStream in) {
  2.         this(in, defaultBufferSize);
  3.     }

  4. public BufferedInputStream(InputStream in, int size) {
  5.         super(in);
  6.         if (size <= 0) {
  7.             throw new IllegalArgumentException("Buffer size <= 0");
  8.         }
  9.         buf = new byte[size];
  10. }
可以看到,BufferedInputStream的构造函数是从一个InputStream的实例构造而来,并且可以根据指定的size来初始化对应大小的内部数组。并且看内部函数fill()

点击(此处)折叠或打开

  1. private void fill() throws IOException {
  2.         byte[] buffer = getBufIfOpen();
  3.         if (markpos < 0)
  4.             pos = 0; /* no mark: throw away the buffer */
  5.         else if (pos >= buffer.length) /* no room left in buffer */
  6.             if (markpos > 0) { /* can throw away early part of the buffer */
  7.                 int sz = pos - markpos;
  8.                 System.arraycopy(buffer, markpos, buffer, 0, sz);
  9.                 pos = sz;
  10.                 markpos = 0;
  11.             } else if (buffer.length >= marklimit) {
  12.                 markpos = -1; /* buffer got too big, invalidate mark */
  13.                 pos = 0; /* drop buffer contents */
  14.             } else { /* grow buffer */
  15.                 int nsz = pos * 2;
  16.                 if (nsz > marklimit)
  17.                     nsz = marklimit;
  18.                 byte nbuf[] = new byte[nsz];  //此处生成一个新的大小的数组
  19.                 System.arraycopy(buffer, 0, nbuf, 0, pos);  //把原来数组中的数据拷贝过去
  20.                 if (!bufUpdater.compareAndSet(this, buffer, nbuf)) {
  21.                     // Can't replace buf if there was an async close.
  22.                     // Note: This would need to be changed if fill()
  23.                     // is ever made accessible to multiple threads.
  24.                     // But for now, the only way CAS can fail is via close.
  25.                     // assert buf == null;
  26.                     throw new IOException("Stream closed");
  27.                 }
  28.                 buffer = nbuf; //内部数组指定为新建立的数组
  29.             }
  30.         count = pos;
  31.         int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
  32.         if (n > 0)
  33.             count = n + pos;
  34.     }
可知,BufferedInputStream内部的数组大小是可以更改的。

2. 第二个不同在于无论ByteArrayInputStream如何调用read,它都是在返回内部固定的数组中的数值。
如果当前位置超过了数组的count,那么返回-1

点击(此处)折叠或打开

  1. public synchronized int read() {
  2.     return (pos < count) ? (buf[pos++] & 0xff) : -1;
  3.     }
而对于BufferedInputStream, 当其调用read()时候,如果当前的位置超过了数组的count,BufferedInputStream会去从底层的inputStream去读取新的数据,填充到内部数组中。

点击(此处)折叠或打开
  1. public synchronized int read() throws IOException {
  2.         if (pos >= count) {
  3.             fill(); //读取新的数据
  4.             if (pos >= count)
  5.                 return -1;
  6.         }
  7.         return getBufIfOpen()[pos++] & 0xff;
  8.     }











阅读(14543) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~