ByteArrayInputStream是字节数组输入流,继承InputStream,它里面维护一个缓冲区,也就是一个byte类型的数组,通过一个计数器pos来实现对字节数组的读取。与之相对应的ByteArrayOutputStream是字节数组输出流,继承自OutputStream,它里面也维护一个缓冲区,通过一个计数器count来实现对字节数组的操作。具体实现如下
1 package java.io; 2 3 4 public class ByteArrayInputStream extends InputStream { 5 6 //字节缓冲区 7 protected byte buf[]; 8 9 //当前读取字节的位置 10 protected int pos; 11 12 //标记字节的位置,如果没有标记,则为0 13 protected int mark = 0; 14 15 //记录字节数组的长度 16 protected int count; 17 18 //构造函数,初始化相关的参数 19 public ByteArrayInputStream(byte buf[]) { 20 this.buf = buf; 21 this.pos = 0; 22 this.count = buf.length; 23 } 24 25 //根据传入的字节数组的起始位置和读取长度的构造函数 26 public ByteArrayInputStream(byte buf[], int offset, int length) { 27 this.buf = buf; 28 this.pos = offset; 29 this.count = Math.min(offset + length, buf.length); 30 this.mark = offset; 31 } 32 33 //返回当前pos位置上字节的值 34 public synchronized int read() { 35 //如果当前pos的位置的值超过了byte的最大的值,则和0xff与运算,获取正值 36 return (pos < count) ? (buf[pos++] & 0xff) : -1; 37 } 38 39 //把当前字节流里面的数据读取到传入的字节数组中 40 public synchronized int read(byte b[], int off, int len) { 41 if (b == null) { 42 throw new NullPointerException(); 43 } else if (off < 0 || len < 0 || len > b.length - off) { 44 throw new IndexOutOfBoundsException(); 45 } 46 47 if (pos >= count) { 48 return -1; 49 } 50 //获取当前缓冲的剩余大小 51 int avail = count - pos; 52 //如果写入b的长度大于当前缓冲区的大小,则更新写入的长度为当前缓冲区的大小 53 if (len > avail) { 54 len = avail; 55 } 56 if (len <= 0) { 57 return 0; 58 } 59 //调用native方法把当前缓冲区的内容复制到b中 60 System.arraycopy(buf, pos, b, off, len); 61 pos += len; 62 return len; 63 } 64 65 //跳过指定的字节大小,如果当前跳过的大小大于剩余的字节的数量,则跳过剩余字节的数量 66 public synchronized long skip(long n) { 67 long k = count - pos; 68 if (n < k) { 69 k = n < 0 ? 0 : n; 70 } 71 72 pos += k; 73 return k; 74 } 75 76 //返回当前还有多少个字节可读取 77 public synchronized int available() { 78 return count - pos; 79 } 80 81 //是否支持标记 82 public boolean markSupported() { 83 return true; 84 } 85 86 //把字节流的标记位标记到当前流读取的位置,不支持传入的参数 87 public void mark(int readAheadLimit) { 88 mark = pos; 89 } 90 91 //重置当前流到标记的位置开始读取 92 public synchronized void reset() { 93 pos = mark; 94 } 95 96 //该字节流在内存中操作,不需要关闭 97 public void close() throws IOException { 98 } 99 100 }
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) { // overflow-conscious code
//如果当前缓冲区的大小不能继续存放字节,则扩容
if (minCapacity - buf.length > 0) grow(minCapacity); } //字节流缓冲扩容 private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = buf.length; int newCapacity = oldCapacity << 1; //最小扩容为原来的一倍 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity < 0) {//超过Integer的大小,则变为负数 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开始写入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; } //把一个outputStream中存储的数据写入到当前字节流数组 public synchronized void writeTo(OutputStream out) throws IOException { out.write(buf, 0, count); } //重置字节流数组的读取的位置为0 public synchronized void reset() { count = 0; } //把字节流转换成字节数组 public synchronized byte toByteArray()[] { return Arrays.copyOf(buf, count); } //返回当前字节流数组读取的位置 public synchronized int size() { return count; } //根据默认的字节编码来把字节流转换成string 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 { } }
1 package com.zwc.io.test; 2 3 import java.io.ByteArrayInputStream; 4 import java.io.ByteArrayOutputStream; 5 import java.io.IOException; 6 import java.io.UnsupportedEncodingException; 7 8 public class TestByteArray { 9 private static final String STRING1 = "好好学习,天天向上,good good study, day day up"; 10 public static void main(String[] args) throws Exception { 11 testByteArrayInputStream(); 12 System.out.println("====================="); 13 testByteArrayOutputStream(); 14 15 } 16 private static void testByteArrayOutputStream() throws Exception{ 17 ByteArrayOutputStream bos = new ByteArrayOutputStream(66); 18 bos.write(STRING1.getBytes("utf-8")); 19 System.out.println(bos.size()); 20 System.out.println(bos.toString("utf-8")); 21 byte[] bytes = bos.toByteArray(); 22 bos.reset();//重置当前字节输出流的位置到开始位置 23 bos.write(bytes);//重新把字节数组写入到bos中 24 System.out.println(bos.toString("utf-8")); 25 26 } 27 private static void testByteArrayInputStream() 28 throws UnsupportedEncodingException, IOException { 29 byte[] bytes = STRING1.getBytes("utf-8"); 30 ByteArrayInputStream bis = new ByteArrayInputStream(bytes); 31 if(bis.markSupported()) { 32 bis.mark(0);//表示从0的位置开始标记,0实际上没有意义,只会从当前流的cout位置标记,也就是把mark = cout 33 } 34 bis.skip(30);//跳过30个字节 35 byte[] out = new byte[bis.available()]; 36 bis.read(out); 37 System.out.println(new String(out, "utf-8")); 38 bis.reset();//回到0标记的位置 39 out = new byte[bis.available()];//重新初始化字节数组 40 bis.read(out); 41 System.out.println(new String(out, "utf-8")); 42 } 43 }
执行结果:
good good study, day day up
好好学习,天天向上,good good study, day day up
=====================
57
好好学习,天天向上,good good study, day day up
好好学习,天天向上,good good study, day day up
java(jdk1.7) IO系列02之ByteArrayInputStream和ByteArrayOutputStream解析
原文:http://www.cnblogs.com/flyinjava/p/6446069.html