Java IO 过滤流 字节缓冲流 BufferedInput/OutputStream
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Java IO 过滤流 字节缓冲流 BufferedInput/OutputStream,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5355字,纯文字阅读大概需要8分钟。
内容图文
![Java IO 过滤流 字节缓冲流 BufferedInput/OutputStream](/upload/InfoBanner/zyjiaocheng/1324/02774afe7a2245318abd805cc4e4fbda.jpg)
Java IO 过滤流 字节缓冲流 BufferedInput/OutputStream
@author ixenos
概念
BufferedInput/OutputStream是实现缓存的过滤流,他们分别是FilterInput/OutputStream的子类。
BufferedInputStream工作流程
stream-->buf--read buf-->I
1.当一个BufferedInputStream被创建时,一个内部的缓冲区 byte[] buf = new byte[size] 也被建立,size默认是8192也就是默认创建一个8kb大小的缓存空间,BufferedInputStream预先在缓冲区存储来自连接输入流的数据;
1 private static int DEFAULT_BUFFER_SIZE = 8192; 2protectedvolatilebyte buf[]; 3 4public BufferedInputStream(InputStream in) { 5this(in, DEFAULT_BUFFER_SIZE); 6 } 7 8 9public BufferedInputStream(InputStream in, int size) { 10super(in); 11if (size <= 0) { 12thrownew IllegalArgumentException("Buffer size <= 0"); 13 } 14 buf = newbyte[size]; 15 }
2.当BufferedInputStream的read方法被调用时,数据将从缓冲区中移出,而不是底层的输入流;
3.当BufferedInputStream缓冲区数据用完时,他自动从底层输入流中补充数据。
BufferedInputStream的read方法源码分析
1 public synchronized int read() throws IOException { 2if (pos >= count) { 3 fill(); 4if (pos >= count) 5return -1; 6 } 7return getBufIfOpen()[pos++] & 0xff; 8 } 910//getBufIfOpen对buf进行非空判断,然后返回buf值传递给buffer的一个byte[]数组11privatebyte[] getBufIfOpen() throws IOException { 12byte[] buffer = buf; 13if (buffer == null) 14thrownew IOException("Stream closed"); 15return buffer; 16 }
BufferedInputStream的read(byte b[], int off, int len)源码分析
1 // BufferedInputStream中的read进指定内存的方法 2 public synchronized int read(byte b[], int off, int len) 3throws IOException 4 { 5//缓冲流关闭时维护的buf消失,返回的buffer等于null,因为buf值传递给buffer,如下 6/* 7 private byte[] getBufIfOpen() throws IOException { 8 byte[] buffer = buf; 9 if (buffer == null) 10 throw new IOException("Stream closed"); 11 return buffer; 12 } 13*/ 14 getBufIfOpen(); // Check for closed stream 15//范围判断 16if ((off | len | (off + len) | (b.length - (off + len))) < 0) { 17thrownew IndexOutOfBoundsException(); 18 } elseif (len == 0) { 19return 0; 20 } 21 22int n = 0; 23//循环写数据到b,知道buffer数据不足返回-1,此时nread已累加记录 24for (;;) { 25int nread = read1(b, off + n, len - n); 26if (nread <= 0) 27return (n == 0) ? nread : n; 28 n += nread; 29//读完指定长度时返回 30if (n >= len) 31return n; 32// if not closed but no bytes available, return 33//没读完指定长度,但缓冲区没数据时返回当前n 34 InputStream input = in; 35if (input != null && input.available() <= 0) 36return n; 37 } 38 } 39 40 41/** 42 * read1方法是该read底层用来读取缓冲区buf的数据进指定数组的方法 43 * 而fill方法又是read1方法中用来读取底层字节流到缓冲区buf的方法 44 * 读取数据写进指定数组的一部分,必要时每次从底层流尽量读取数据 45*/ 46privateint read1(byte[] b, int off, int len) throws IOException { 47int avail = count - pos; 48if (avail <= 0) { 49/* 如果所请求的长度至少和缓冲区一样大,并且 50 如果没有标记/复位活动,就没必要用缓冲区了,将直接从底层 流读取数据。以这种方式缓冲流将 51 级联无害 52*/ 53if (len >= getBufIfOpen().length && markpos < 0) { 54//getInIfOpen返回的是经非空判断的底层流,所以调用的自然也是底层流的read方法,写进指定的内存b 55return getInIfOpen().read(b, off, len); 56 } 57//请求fill()方法来读取底层流数据 58 fill(); 59 avail = count - pos; 60if (avail <= 0) return -1; 61 } 62int cnt = (avail < len) ? avail : len; 63 System.arraycopy(getBufIfOpen(), pos, b, off, cnt); 64 pos += cnt; 65return cnt; 66 } 67 68 69//fill()方法填充空间,是底层用来读取流数据到缓冲区buf 70/** 71 * Fills the buffer with more data, taking into account 72 * shuffling and other tricks for dealing with marks. 73 * Assumes that it is being called by a synchronized method. 74 * This method also assumes that all data has already been read in, 75 * hence pos > count. 76*/ 77privatevoid fill() throws IOException { 78byte[] buffer = getBufIfOpen(); 79//markpos是起始读取buffer的位置,pos是终点位置 80//起始小于零表明没有pos移动,从源码可知 81if (markpos < 0) 82 pos = 0; /* no mark: throw away the buffer */ 83//当pos比buffer更长时 84elseif (pos >= buffer.length) /* no room left in buffer */ 85//起始pos也有前移时 86if (markpos > 0) { /* can throw away early part of the buffer */ 87int sz = pos - markpos; 88 System.arraycopy(buffer, markpos, buffer, 0, sz); 89 pos = sz; 90 markpos = 0; 91//buffer大小超过理论规模时 92 } elseif (buffer.length >= marklimit) { 93 markpos = -1; /* buffer got too big, invalidate mark */ 94 pos = 0; /* drop buffer contents */ 95//buffer大小超过本地VM内存限制时:MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8 96 } elseif (buffer.length >= MAX_BUFFER_SIZE) { 97thrownew OutOfMemoryError("Required array size too large"); 98 } else { /* grow buffer */ 99int nsz = (pos <= MAX_BUFFER_SIZE - pos) ? 100 pos * 2 : MAX_BUFFER_SIZE; 101if (nsz > marklimit) 102 nsz = marklimit; 103byte nbuf[] = newbyte[nsz]; 104 System.arraycopy(buffer, 0, nbuf, 0, pos); 105/*AtomicReferenceFieldUpdater是一个基于反射的工具类, 106它能对指定类的指定的volatile引用字段进行原子更新。 107(注意这个字段不能是private的) , 108从源码知getBufIfOpen返回的是值传递的protected volatile byte buf[] 109*/110if (!bufUpdater.compareAndSet(this, buffer, nbuf)) { 111// Can‘t replace buf if there was an async close. 112// Note: This would need to be changed if fill() 113// is ever made accessible to multiple threads. 114// But for now, the only way CAS can fail is via close. 115// assert buf == null;116thrownew IOException("Stream closed"); 117 } 118 buffer = nbuf; 119 } 120//pos小于buf.length时,从底层流到缓冲区,使用InputStream的read(byte[])方法121 count = pos; 122int n = getInIfOpen().read(buffer, pos, buffer.length - pos); 123if (n > 0) 124 count = n + pos; 125 } 126
BufferedOutputStream工作流程
I--write buf-->buf-->stream
1.BufferedOutputStream在内部缓冲区存储程序的输出数据,这样就不会每次调用write方法时,就把数据写到底层的输出流;
2.当BufferedOutputStream的内部缓冲区满或者它被刷新(flush),数据一次性写到底层的输出流。
原文:http://www.cnblogs.com/ixenos/p/5729841.html
内容总结
以上是互联网集市为您收集整理的Java IO 过滤流 字节缓冲流 BufferedInput/OutputStream全部内容,希望文章能够帮你解决Java IO 过滤流 字节缓冲流 BufferedInput/OutputStream所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。