这里有一个关于 BufferedOutputStream源代码的描述,应该对你理解 BufferedOutputStream流有帮助。
package java.io;
019
020 import org.apache.harmony.luni.util.Msg;
021
022 // BEGIN android-added
023 import java.util.logging.Logger;
024 // END android-added
025
026 /***
027 * Wraps an existing {@link OutputStream} and <em>buffers</em> the output.
028 * Expensive interaction with the underlying input stream is minimized, since
029 * most (smaller) requests can be satisfied by accessing the buffer alone. The
030 * drawback is that some extra space is required to hold the buffer and that
031 * copying takes place when flushing that buffer, but this is usually outweighed
032 * by the performance benefits.
033 *
034 * <p/>A typical application pattern for the class looks like this:<p/>
035 *
036 * <pre>
037 * BufferedOutputStream buf = new BufferedOutputStream(new FileOutputStream("file.java"));
038 * </pre>
039 *
040 * @see BufferedInputStream
041 */
042 public class BufferedOutputStream extends FilterOutputStream {
043 /***
044 * The buffer containing the bytes to be written to the target stream.
045 */
046 protected byte[] buf;
047
048 /***
049 * The total number of bytes inside the byte array {@code buf}.
050 */
051 protected int count;
052
053 /***
054 * Constructs a new {@code BufferedOutputStream} on the {@link OutputStream}
055 * {@code out}. The buffer size is set to the default value of 8 KB.
056 *
057 * @param out
058 * the {@code OutputStream} for which write operations are
059 * buffered.
060 */
061 public BufferedOutputStream(OutputStream out) {
062 super(out);
063 buf = new byte[8192];
064
065 // BEGIN android-added
066 /**
067 * For Android, we want to discourage the use of this constructor (with
068 * its arguably too-large default), so we note its use in the log. We
069 * don't disable it, nor do we alter the default, however, because we
070 * still aim to behave compatibly, and the default value, though not
071 * documented, is established by convention.
072 */
073 Logger.global.info(
074 "Default buffer size used in BufferedOutputStream " +
075 "constructor. It would be " +
076 "better to be explicit if an 8k buffer is required.");
077 // END android-added
078 }
079
080 /***
081 * Constructs a new {@code BufferedOutputStream} on the {@link OutputStream}
082 * {@code out}. The buffer size is set to {@code size}.
083 *
084 * @param out
085 * the output stream for which write operations are buffered.
086 * @param size
087 * the size of the buffer in bytes.
088 * @throws IllegalArgumentException
089 * if {@code size <= 0}.
090 */
091 public BufferedOutputStream(OutputStream out, int size) {
092 super(out);
093 if (size <= 0) {
094 // K0058=size must be > 0
095 throw new IllegalArgumentException(Msg.getString("K0058")); //$NON-NLS-1$
096 }
097 buf = new byte[size];
098 }
099
100 /***
101 * Flushes this stream to ensure all pending data is written out to the
102 * target stream. In addition, the target stream is flushed.
103 *
104 * @throws IOException
105 * if an error occurs attempting to flush this stream.
106 */
107 @Override
108 public synchronized void flush() throws IOException {
109 if (buf == null) {
110 throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
111 }
112
113 flushInternal();
114 out.flush();
115 }
116
117 /***
118 * Writes {@code count} bytes from the byte array {@code buffer} starting at
119 * {@code offset} to this stream. If there is room in the buffer to hold the
120 * bytes, they are copied in. If not, the buffered bytes plus the bytes in
121 * {@code buffer} are written to the target stream, the target is flushed,
122 * and the buffer is cleared.
123 *
124 * @param buffer
125 * the buffer to be written.
126 * @param offset
127 * the start position in {@code buffer} from where to get bytes.
128 * @param length
129 * the number of bytes from {@code buffer} to write to this
130 * stream.
131 * @throws IndexOutOfBoundsException
132 * if {@code offset < 0} or {@code length < 0}, or if
133 * {@code offset + length} is greater than the size of
134 * {@code buffer}.
135 * @throws IOException
136 * if an error occurs attempting to write to this stream.
137 * @throws NullPointerException
138 * if {@code buffer} is {@code null}.
139 * @throws ArrayIndexOutOfBoundsException
140 * If offset or count is outside of bounds.
141 */
142 @Override
143 public synchronized void write(byte[] buffer, int offset, int length)
144 throws IOException {
145 byte[] internalBuffer = buf;
146 if (internalBuffer == null) {
147 throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
148 }
149
150 if (buffer == null) {
151 // K0047=buffer is null
152 throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
153 }
154
155 if (length >= internalBuffer.length) {
156 flushInternal();
157 out.write(buffer, offset, length);
158 return;
159 }
160
161 if (offset < 0 || offset > buffer.length - length) {
162 // K002e=Offset out of bounds \: {0}
163 throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
164
165 }
166 if (length < 0) {
167 // K0031=Length out of bounds \: {0}
168 throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
169 }
170
171 // flush the internal buffer first if we have not enough space left
172 if (length >= (internalBuffer.length - count)) {
173 flushInternal();
174 }
175
176 // the length is always less than (internalBuffer.length - count) here so arraycopy is safe
177 System.arraycopy(buffer, offset, internalBuffer, count, length);
178 count += length;
179 }
180
181 @Override public synchronized void close() throws IOException {
182 if (buf == null) {
183 return;
184 }
185
186 try {
187 super.close();
188 } finally {
189 buf = null;
190 }
191 }
192
193 /***
194 * Writes one byte to this stream. Only the low order byte of the integer
195 * {@code oneByte} is written. If there is room in the buffer, the byte is
196 * copied into the buffer and the count incremented. Otherwise, the buffer
197 * plus {@code oneByte} are written to the target stream, the target is
198 * flushed, and the buffer is reset.
199 *
200 * @param oneByte
201 * the byte to be written.
202 * @throws IOException
203 * if an error occurs attempting to write to this stream.
204 */
205 @Override
206 public synchronized void write(int oneByte) throws IOException {
207 byte[] internalBuffer = buf;
208 if (internalBuffer == null) {
209 throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
210 }
211
212 if (count == internalBuffer.length) {
213 out.write(internalBuffer, 0, count);
214 count = 0;
215 }
216 internalBuffer[count++] = (byte) oneByte;
217 }
218
219 /***
220 * Flushes only internal buffer.
221 */
222 private void flushInternal() throws IOException {
223 if (count > 0) {
224 out.write(buf, 0, count);
225 count = 0;
226 }
227 }
228 }
|