Java字节流:ByteArrayInputStream ByteArrayOutputStream
-----------------------------------------------------------------------------------
ByteArrayInputStream
类声明:public class ByteArrayInputStream extends InputStream
位于java.io包下
官方对其说明:
A ByteArrayInputStream contains an internal buffer that contains bytes that may be read from the stream. An internal counter keeps track of the next byte to be supplied by the read method.
(简单翻译:ByteArrayInputStream包含一个内部缓冲区,该缓冲区包含从流中读取的字节数据。内部计数器跟踪read方法要提供的下一个字节)
Closing a ByteArrayInputStream has no effect. The methods in this class can be called after the stream has been closed without generating an IOException.
(简单翻译:关闭ByteArrayInputStream无效,此类中的方法在关闭此流后仍可被调用,而不会产生IOException)
主要字段:
protected byte[] buf: 存储输入流中的字节数组
protected int count: 输入流中字节的个数
protected int mark: 流中当前的标记位置
protected int pos: 要从输入流缓冲区中读取的下一个字节的索引
构造方法:
ByteArrayInputStream(byte[] buf);
创建一个ByteArrayInputStream实例,使用字节数组buf作为其缓冲区数组。
ByteArrayInputStream(byte[] buf,int offset,int length);
创建一个ByteArrayInputStream实例,使用字节数组buf从offset开始的len个字节作为其缓冲区数组。
主要方法:
- int available(): 输入流中可读取的字节个数
- void close(): 关闭此输入流并释放与该流有关的系统资源.
- void mark(int readlimit): 在此输入流中标记当前的位置.
- boolean markSupported(): 检测此输入流是否支持mark和reset.
- int read(): 从输入流中读取下一个字节数据.
- int read(byte[] b,int off,int len): 从输入流中读取len个字节,并将其存储在字节数组b中off位置开始的地方
- void reset(): 将此流重新定位到最后一次对此输入流调用mark方法时的位置.
- long skip(long n): 跳过和丢弃此输入流中n个字节的数据.
通过实例演示查看源代码:
通过构造方法ByteArrayInputStream(byte[] buf)来创建一个ByteArrayInputStream类的实例
byte[] bytes = new byte[]{'a','b','c','d','e','f','g','h','j','k'};
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
查看ByteArrayInputStream(byte[] buf)构造方法的源代码:
1 public ByteArrayInputStream(byte buf[]) { 2 this.buf = buf; 3 this.pos = 0; 4 this.count = buf.length; 5 }
此时ByteArrayInputStream实例在内存中的情况如下图,可以看出构造函数的参数 byte buf[]就是输入流中的数据。
实例byteArrayInputStream中的属性 count = 10、mark = 0、pos = 0;
下面来看看具体的方法
(1)int available()方法
功能: 返回输入流中还能够被读取的字节个数
源代码如下:
1 /** 2 * Returns the number of remaining bytes that can be read (or skipped over) 3 * from this input stream. 4 * <p> 5 * The value returned is <code>count - pos</code>, 6 * which is the number of bytes remaining to be read from the input buffer. 7 * 8 * @return the number of remaining bytes that can be read (or skipped 9 * over) from this input stream without blocking. 10 */ 11 public synchronized int available() { 12 return count - pos; 13 }
执行:byteArrayInputStream.available()方法 返回值是10。(available()方法的返回值会随着pos的增大而变小)
(2)void close()方法
功能: 关闭输入流(但ByteArrayInputStream此方法无效)
源代码如下:
1 /** 2 * Closing a <tt>ByteArrayInputStream</tt> has no effect. The methods in 3 * this class can be called after the stream has been closed without 4 * generating an <tt>IOException</tt>. 5 * <p> 6 */ 7 public void close() throws IOException { 8 }
执行:byteArrayInputStream.close()方法 没有任何的效果,因为源代码中方法体没有任何的代码.
(3)int read()方法
功能: 从输入流中读取下一个字节数据
源代码如下:
1 /** 2 * Reads the next byte of data from this input stream. The value 3 * byte is returned as an <code>int</code> in the range 4 * <code>0</code> to <code>255</code>. If no byte is available 5 * because the end of the stream has been reached, the value 6 * <code>-1</code> is returned. 7 * <p> 8 * This <code>read</code> method 9 * cannot block. 10 * 11 * @return the next byte of data, or <code>-1</code> if the end of the 12 * stream has been reached. 13 */ 14 public synchronized int read() { 15 return (pos < count) ? (buf[pos++] & 0xff) : -1; 16 }
执行:byteArrayInputStream.read()方法,返回值为: 97.
此时ByteArrayInputStream实例在内存中的情况如下图,此时属性pos的为1.
(4)boolean markSupported()
功能: 检测此输入流是否支持mark()和reset()
源代码如下:
1 /** 2 * Tests if this <code>InputStream</code> supports mark/reset. The 3 * <code>markSupported</code> method of <code>ByteArrayInputStream</code> 4 * always returns <code>true</code>. 5 * 6 * @since JDK1.1 7 */ 8 public boolean markSupported() { 9 return true; 10 }
执行:byteArrayInputStream.markSupported()方法,返回值为: true
(5)下面三个方法主要是用来修改ByteArrayInputStream类实例中的 pos和mark属性的。
void mark(int readlimit): 在此输入流中标记当前的位置.
void reset(): 将此流重新定位到最后一次对此输入流调用mark方法时的位置.
long skip(long n): 跳过和丢弃此输入流中n个字节的数据.
void mark(int readlimit)
功能:在此输入流中标记当前的位置
源码如下:
1 /** 2 * Set the current marked position in the stream. 3 * ByteArrayInputStream objects are marked at position zero by 4 * default when constructed. They may be marked at another 5 * position within the buffer by this method. 6 * <p> 7 * If no mark has been set, then the value of the mark is the 8 * offset passed to the constructor (or 0 if the offset was not 9 * supplied). 10 * 11 * <p> Note: The <code>readAheadLimit</code> for this class 12 * has no meaning. 13 * 14 * @since JDK1.1 15 */ 16 public void mark(int readAheadLimit) { 17 mark = pos; 18 }
执行:byteArrayInputStream.mark(8)方法,可以看出参数readAheadLimit没有用。
此时ByteArrayInputStream实例在内存中的情况如下图,此时属性mark的值为1
void skip(long n)
功能:将此流重新定位到最后一次对此输入流调用mark方法时的位置.
源代码如下:
1 /** 2 * Skips <code>n</code> bytes of input from this input stream. Fewer 3 * bytes might be skipped if the end of the input stream is reached. 4 * The actual number <code>k</code> 5 * of bytes to be skipped is equal to the smaller 6 * of <code>n</code> and <code>count-pos</code>. 7 * The value <code>k</code> is added into <code>pos</code> 8 * and <code>k</code> is returned. 9 * 10 * @param n the number of bytes to be skipped. 11 * @return the actual number of bytes skipped. 12 */ 13 public synchronized long skip(long n) { 14 long k = count - pos; 15 if (n < k) { 16 k = n < 0 ? 0 : n; 17 } 18 19 pos += k; 20 return k; 21 }
执行:byteArrayInputStream.skip(5)方法后,属性pos的值为6。(从输入流中跳过了5个字节)
此时ByteArrayInputStream实例在内存中的情况如下图,此时属性pos的值为6,也就是说下一次调用read()方法时,返回输入流中索引为6位置的值.
void reset()方法
功能:将此流重新定位到最后一次对此输入流调用mark方法时的位置
源代码如下:
1 /** 2 * Resets the buffer to the marked position. The marked position 3 * is 0 unless another position was marked or an offset was specified 4 * in the constructor. 5 */ 6 public synchronized void reset() { 7 pos = mark; 8 }
执行:byteArrayInputStream.reset()方法后,pos属性值为1。
此时ByteArrayInputStream实例在内存中的情况如下图,此时pos属性的值为1,下一次调用read()方法时,返回输入流中索引为1位置的值
(6)int read(byte[] b,int off,int len)方法
功能:从输入流中读取len个字节,并将其存储在字节数组b中off位置开始的地方
源代码如下:
1 /** 2 * Reads up to <code>len</code> bytes of data into an array of bytes 3 * from this input stream. 4 * If <code>pos</code> equals <code>count</code>, 5 * then <code>-1</code> is returned to indicate 6 * end of file. Otherwise, the number <code>k</code> 7 * of bytes read is equal to the smaller of 8 * <code>len</code> and <code>count-pos</code>. 9 * If <code>k</code> is positive, then bytes 10 * <code>buf[pos]</code> through <code>buf[pos+k-1]</code> 11 * are copied into <code>b[off]</code> through 12 * <code>b[off+k-1]</code> in the manner performed 13 * by <code>System.arraycopy</code>. The 14 * value <code>k</code> is added into <code>pos</code> 15 * and <code>k</code> is returned. 16 * <p> 17 * This <code>read</code> method cannot block. 18 * 19 * @param b the buffer into which the data is read. 20 * @param off the start offset in the destination array <code>b</code> 21 * @param len the maximum number of bytes read. 22 * @return the total number of bytes read into the buffer, or 23 * <code>-1</code> if there is no more data because the end of 24 * the stream has been reached. 25 * @exception NullPointerException If <code>b</code> is <code>null</code>. 26 * @exception IndexOutOfBoundsException If <code>off</code> is negative, 27 * <code>len</code> is negative, or <code>len</code> is greater than 28 * <code>b.length - off</code> 29 */ 30 public synchronized int read(byte b[], int off, int len) { 31 if (b == null) { 32 throw new NullPointerException(); 33 } else if (off < 0 || len < 0 || len > b.length - off) { 34 throw new IndexOutOfBoundsException(); 35 } 36 37 if (pos >= count) { 38 return -1; 39 } 40 41 int avail = count - pos; 42 if (len > avail) { 43 len = avail; 44 } 45 if (len <= 0) { 46 return 0; 47 } 48 System.arraycopy(buf, pos, b, off, len); 49 pos += len; 50 return len; 51 }
执行:byteArrayInputStream.read(b,0,5)方法后,b数组中的值为['b','c','d','e','f'].
此时ByteArrayInputStream实例在内存中的情况如下图,属性pos的值为6.
------------------------------------------------------------------------
ByteArrayOutputStream
类声明:public class ByteArrayOutputStream extends OutputStream
位于java.io包下
官方对其说明:
This class implements an output stream in which the data is written into a byte array. The buffer automatically grows as data is written to it. The data can be retrieved using toByteArray() and toString().
(简单翻译:ByteArrayInputStream实现了一个输出流,其中的数据被写入一个byte数组。缓冲区会随着数据的不断写入而自动增长。可以使用toByteArray()和toString()方法来获取数据)
Closing a ByteArrayOutputStream has no effect. The methods in this class can be called after the stream has been closed without generating an IOException.
(简单翻译:关闭ByteArrayOutputStream无效,此类中的方法在关闭此流后仍可被调用,而不会产生IOException)
主要字段:
protected byte[] buf: 存储数据的缓冲区
protected int count: 缓冲区中的有效字节数
构造方法:
ByteArrayOutputStream(): 创建一个新的byte数组输出流。
ByteArrayOutputStream(int size): 创建一个新的byte数组输出流,它具有指定大小的缓冲区容量(以字节为单位)。
主要方法:
- void close():
- void reset():
- int size(): 返回缓冲区的当前大小
- byte[] toByteArray(): 创建一个新分配的byte数组
- String toString():
- String toString(String charsetName):
- void write(byte[] b,int off,int len):
- void write(int b):
- void writeTo(OutputStream out):
通过实例演示查看源代码:
通过构造方法ByteArrayOutputStream()来创建一个ByteArrayOutputStream类的实例
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
查看ByteArrayOutputStream()构造方法的源代码:
1 /** 2 * Creates a new byte array output stream. The buffer capacity is 3 * initially 32 bytes, though its size increases if necessary. 4 */ 5 public ByteArrayOutputStream() { 6 this(32); 7 } 8 9 /** 10 * Creates a new byte array output stream, with a buffer capacity of 11 * the specified size, in bytes. 12 * 13 * @param size the initial size. 14 * @exception IllegalArgumentException if size is negative. 15 */ 16 public ByteArrayOutputStream(int size) { 17 if (size < 0) { 18 throw new IllegalArgumentException("Negative initial size: " 19 + size); 20 } 21 buf = new byte[size]; 22 }
此时ByteArrayOutputStream实例在内存中的情况如下图:
下面来看看具体的方法:
(1)int close()方法
功能: 无效,源代码中什么代码都没有。
源代码如下:
1 /** 2 * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in 3 * this class can be called after the stream has been closed without 4 * generating an <tt>IOException</tt>. 5 * <p> 6 * 7 */ 8 public void close() throws IOException { 9 }
执行:byteArrayOutputStream.close()方法,不会有任何效果。
(2)void write(int b)
功能: 将指定的数据 写入到此输出流中
源代码如下:
1 /** 2 * Writes the specified byte to this byte array output stream. 3 * 4 * @param b the byte to be written. 5 */ 6 public synchronized void write(int b) { 7 ensureCapacity(count + 1); 8 buf[count] = (byte) b; 9 count += 1; 10 }
执行:byteArrayOutputStream.write(97)方法
执行:byteArrayOutputStream.write(98)方法
执行:byteArrayOutputStream.write(99)方法
执行:byteArrayOutputStream.write(100)方法
此时ByteArrayOutputStream实例在内存中的情况如下图:
(3)void write(byte b[], int off, int len)
功能: 将指定的字节数组b 从off位置开始的len个字节 写入到此输出流中。
源代码如下:
1 /** 2 * Writes <code>len</code> bytes from the specified byte array 3 * starting at offset <code>off</code> to this byte array output stream. 4 * 5 * @param b the data. 6 * @param off the start offset in the data. 7 * @param len the number of bytes to write. 8 */ 9 public synchronized void write(byte b[], int off, int len) { 10 if ((off < 0) || (off > b.length) || (len < 0) || 11 ((off + len) - b.length > 0)) { 12 throw new IndexOutOfBoundsException(); 13 } 14 ensureCapacity(count + len); 15 System.arraycopy(b, off, buf, count, len); 16 count += len; 17 }
执行:
byte[] b = new byte[]{'z','x','c','f'}
byteArrayOutputStream.write(b,1,2)方法
此时ByteArrayOutputStream实例在内存中的情况如下图:
(4)void size()
功能:返回输出流中字节个数
源代码如下:
1 /** 2 * Returns the current size of the buffer. 3 * 4 * @return the value of the <code>count</code> field, which is the number 5 * of valid bytes in this output stream. 6 * @see java.io.ByteArrayOutputStream#count 7 */ 8 public synchronized int size() { 9 return count; 10 }
执行:byteArrayOutputStream.size()方法,返回的结果是:6
(5)byte[] toByteArray()
功能:将输出流中的字节数据以字节数组的形式返回
源代码如下:
1 /** 2 * Creates a newly allocated byte array. Its size is the current 3 * size of this output stream and the valid contents of the buffer 4 * have been copied into it. 5 * 6 * @return the current contents of this output stream, as a byte array. 7 * @see java.io.ByteArrayOutputStream#size() 8 */ 9 public synchronized byte toByteArray()[] { 10 return Arrays.copyOf(buf, count); 11 }
执行:byteArrayOutputStream.toByteArray()方法,返回的结果是:97 98 99 100 120 99
(6)String toString()、String toString(String charsetName)
功能:将输出流中的字节数据转换成字符串
源代码如下:
1 /** 2 * Converts the buffer's contents into a string decoding bytes using the 3 * platform's default character set. The length of the new <tt>String</tt> 4 * is a function of the character set, and hence may not be equal to the 5 * size of the buffer. 6 * 7 * <p> This method always replaces malformed-input and unmappable-character 8 * sequences with the default replacement string for the platform's 9 * default character set. The {@linkplain java.nio.charset.CharsetDecoder} 10 * class should be used when more control over the decoding process is 11 * required. 12 * 13 * @return String decoded from the buffer's contents. 14 * @since JDK1.1 15 */ 16 public synchronized String toString() { 17 return new String(buf, 0, count); 18 } 19 20 /** 21 * Converts the buffer's contents into a string by decoding the bytes using 22 * the specified {@link java.nio.charset.Charset charsetName}. The length of 23 * the new <tt>String</tt> is a function of the charset, and hence may not be 24 * equal to the length of the byte array. 25 * 26 * <p> This method always replaces malformed-input and unmappable-character 27 * sequences with this charset's default replacement string. The {@link 28 * java.nio.charset.CharsetDecoder} class should be used when more control 29 * over the decoding process is required. 30 * 31 * @param charsetName the name of a supported 32 * {@linkplain java.nio.charset.Charset </code>charset<code>} 33 * @return String decoded from the buffer's contents. 34 * @exception UnsupportedEncodingException 35 * If the named charset is not supported 36 * @since JDK1.1 37 */ 38 public synchronized String toString(String charsetName) 39 throws UnsupportedEncodingException 40 { 41 return new String(buf, 0, count, charsetName); 42 }
(7)void reset()
功能:将此 byte 数组输出流的 count
字段重置为零,从而丢弃输出流中目前已累积的所有输出。
源代码如下:
1 /** 2 * Resets the <code>count</code> field of this byte array output 3 * stream to zero, so that all currently accumulated output in the 4 * output stream is discarded. The output stream can be used again, 5 * reusing the already allocated buffer space. 6 * 7 * @see java.io.ByteArrayInputStream#count 8 */ 9 public synchronized void reset() { 10 count = 0; 11 }