ByteArrayInputStream是字节输入流,继承自InputStream,内部将一个字节数组作为内部缓冲区,通过read()方法供外界读取字节,同时包含一个成员变量count用来计数累加,count跟着ByteArrayInputStream中read()方法的下一个字节。
ByteArrayInputStream源码
package java.io;
public class ByteArrayInputStream extends InputStream {
//内部缓冲区,保存字节输入流数据
protected byte buf[];
//下一个被读取字节的位置,随着read()方法累加
protected int pos;
//标记位置使用,配合reset()使用,reset()调用会回到上一次标记的位置
protected int mark = 0;
//字节流长度
protected int count;
public ByteArrayInputStream(byte buf[]) {
this.buf = buf;
this.pos = 0;
this.count = buf.length;
}
public ByteArrayInputStream(byte buf[], int offset, int length) {
this.buf = buf;
this.pos = offset;
this.count = Math.min(offset + length, buf.length);
this.mark = offset;
}
//读取当个字节,pos累加
public synchronized int read() {
return (pos < count) ? (buf[pos++] & 0xff) : -1;
}
//经过一些列的判断,将字节流中的数据存储到b数组中,
//offset表示偏移量,即从off的位置开始取数据
//len表示字节长度,真正取到的字符off位置开始的len个字节
public synchronized int read(byte b[], int off, int len) {
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
}
if (pos >= count) {
return -1;
}
int avail = count - pos;
if (len > avail) {
len = avail;
}
if (len <= 0) {
return 0;
}
System.arraycopy(buf, pos, b, off, len);
pos += len;
return len;
}
//跳过n个字节
public synchronized long skip(long n) {
long k = count - pos;
if (n < k) {
k = n < 0 ? 0 : n;
}
pos += k;
return k;
}
//判断下个存在下个字节
public synchronized int available() {
return count - pos;
}
public boolean markSupported() {
return true;
}
//标记当前位置
public void mark(int readAheadLimit) {
mark = pos;
}
//重置“字节流的读取索引”为“mark所标记的位置”
public synchronized void reset() {
pos = mark;
}
public void close() throws IOException {
}
}
ByteArrayOutputStream是字节输出流,数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() 和 toString() 获取数据。
ByteArrayOutputStream源码:
package java.io;
import java.util.Arrays;
public class ByteArrayOutputStream extends OutputStream {
//内部缓冲数组,存放字节
protected byte buf[];
//当前存放的字节量
protected int count;
//默认容量为32
public ByteArrayOutputStream() {
this(32);
}
public ByteArrayOutputStream(int size) {
if (size < 0) {
throw new IllegalArgumentException("Negative initial size: "
+ size);
}
buf = new byte[size];
}
//检测需否需要扩容,若缓冲数组大小大于扩容的大小,扩容
private void ensureCapacity(int minCapacity) {
if (minCapacity - buf.length > 0)
grow(minCapacity);
}
//扩容操作
private void grow(int minCapacity) {
int oldCapacity = buf.length;
//新容量为旧容量的2倍
int newCapacity = oldCapacity << 1;
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity < 0) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
newCapacity = Integer.MAX_VALUE;
}
buf = Arrays.copyOf(buf, newCapacity);
}
//逐个写入字节
public synchronized void write(int b) {
ensureCapacity(count + 1);
buf[count] = (byte) b;
count += 1;
}
//将b中字节写入到缓冲数组中,off表示b中写入位置的偏移量,len为需要写入的字节量
public synchronized void write(byte b[], int off, int len) {
if ((off < 0) || (off > b.length) || (len < 0) ||
((off + len) - b.length > 0)) {
throw new IndexOutOfBoundsException();
}
ensureCapacity(count + len);
System.arraycopy(b, off, buf, count, len);
count += len;
}
// 写入输出流out到“字节数组输出流”中。
public synchronized void writeTo(OutputStream out) throws IOException {
out.write(buf, 0, count);
}
//重置
public synchronized void reset() {
count = 0;
}
//转化为字节数组
public synchronized byte toByteArray()[] {
return Arrays.copyOf(buf, count);
}
public synchronized int size() {
return count;
}
public synchronized String toString() {
return new String(buf, 0, count);
}
public synchronized String toString(String charsetName)
throws UnsupportedEncodingException
{
return new String(buf, 0, count, charsetName);
}
@Deprecated
public synchronized String toString(int hibyte) {
return new String(buf, hibyte, 0, count);
}
public void close() throws IOException {
}
}
具体应用
byte[] array = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','z','y','z'};
ByteArrayOutputStream baos = null;
ByteArrayInputStream bais = null;
try {
baos = new ByteArrayOutputStream();
//将array写入到baos缓冲数组中
baos.write(array);
System.out.println("baos = "+baos);//baos = abcdefghijklmnopqrstuvwzyz
//重置baos,此时内部的count值为0
baos.reset();
System.out.println("reset baos = "+baos);//reset baos =
//将array中5-20位置的字节写入到baos缓冲数组中
baos.write(array, 5, 15);
System.out.println("offset baos = "+baos);//offset baos = fghijklmnopqrst
//bais中缓冲数组为fghijklmnopqrst
bais = new ByteArrayInputStream(baos.toByteArray());
int count = 0;
StringBuilder str = new StringBuilder();
//循环逐个读取字节,知道返回值为-1,即表示字节白被读完
while((count = bais.read())!=-1) {
//获取到的count是ascii码,强转为char
str.append((char) count);
}
System.out.println("str = "+str.toString());//str = fghijklmnopqrst
//bais中缓冲数组为fghijklmnopqrst
bais = new ByteArrayInputStream(baos.toByteArray());
//将bais中缓存数组的0-5的字节,读入到array中,即将abcde更改为fghij
bais.read(array, 0, 5);
String str1 = new String(array);
System.out.println("str1 = "+str1);//str1 = fghijfghijklmnopqrstuvwzyz
//标记第5个位置
bais.mark(5);
//将内部的pos设置为刚设置的5
bais.reset();
//将bais中缓存数组的0-5的字节,读入到array中,即将fghij更改为klmno
bais.read(array, 0, 5);
String str2 = new String(array);
System.out.println("str2 = " +str2);//str1 = klmnofghijklmnopqrstuvwzyz
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(bais!=null)
bais.close();
if(baos!=null)
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}