博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java IO笔记(ByteArrayInputStream/ByteArrayOutputStream)
阅读量:4876 次
发布时间:2019-06-11

本文共 6789 字,大约阅读时间需要 22 分钟。

今天讲的是ByteArrayInputStream流和ByteArrayOutputStream流。

首先让我们来看看ByteArrayOutputStream的源码:

ByteArrayOutputStream.java

 

package java.io;import java.util.Arrays;public class ByteArrayOutputStream extends OutputStream {    protected byte buf[];    protected int count;    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 static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;    private void grow(int minCapacity) {        // overflow-conscious code        int oldCapacity = buf.length;        int newCapacity = oldCapacity << 1;        if (newCapacity - minCapacity < 0)            newCapacity = minCapacity;        if (newCapacity - MAX_ARRAY_SIZE > 0)            newCapacity = hugeCapacity(minCapacity);        buf = Arrays.copyOf(buf, newCapacity);    }    private static int hugeCapacity(int minCapacity) {        if (minCapacity < 0) // overflow            throw new OutOfMemoryError();        return (minCapacity > MAX_ARRAY_SIZE) ?            Integer.MAX_VALUE :            MAX_ARRAY_SIZE;    }    public synchronized void write(int b) {        ensureCapacity(count + 1);        buf[count] = (byte) b;        count += 1;    }    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;    }    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 {    }}

 

 从源码可以看出,该类继承了OutputStream输出流,其中封装了一个byte类型的数组buf作为数据的缓存区,当进行数据写人的时候,数据会不断地写入buf缓存区中,该缓存区默认大小为32字节。每一次写人数据后,都要执行ensureCapacity方法来确定缓存区容量十分能够容纳写入数据,如果不够的时候会执行grow方法,将容量翻倍以适应写入的数据。当写入完成后,我们可以通过toByteArray方法,来获得缓存区数组的一个副本。因为这个特性,我们可以使用ByteArrayOutputStream进行一次性的数据写入。

下面举例说明ByteArrayOutputStream的使用方法:

 

package ByteArrayIO;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;public class ByteArrayIOTest {	public static void main(String[] args) {		try {			File file = new File("./src/file/test.txt");			FileInputStream fis = new FileInputStream(file);			ByteArrayOutputStream baos = new ByteArrayOutputStream();			int len;			while ((len = fis.read()) != -1) {				baos.write(len);			}			String messages = baos.toString();			System.out.println(messages);			fis.close();			baos.close();		} catch (FileNotFoundException e) {			// TODO Auto-generated catch block			e.printStackTrace();		} catch (IOException e) {			// TODO Auto-generated catch block			e.printStackTrace();		}	}}

执行上述代码,可以在控制台看到以下打印:

 

从打印可以看文件中的所有数据都被存放在了ByteOutputStream中的缓存区中。值得一提的是,ByteArrayOutputStream还介绍到,是否关闭流并不会影响到方法的执行,也就是说,即使流关闭了,数据依然存在。

下面来说说ByteArrayInputStream,首先贴出其源码:

 

package java.io;publicclass ByteArrayInputStream extends InputStream {    protected byte buf[];    protected int pos;    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;    }    public synchronized int read() {        return (pos < count) ? (buf[pos++] & 0xff) : -1;    }    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;    }    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;    }    public synchronized void reset() {        pos = mark;    }    public void close() throws IOException {    }}

从源码中可以看出,ByteArrayInputStream完全是基于字节数组来实现的,下面我们来详细分析一下。

 

ByteArrayInputStream中封装了几个属性:

1.buf数组用于存储从流中读取的数据

2.pos表示下一个即将被读取的字节索引

3.mark表示被标记的索引位置,当调用reset方法时,pos的值重置为mark值。mark方法中的参数无实际意义(也许有,但我没看明白T_T)

4.count表示字节流的总长度。

下面写一个小例子来说明这些方法的使用:

 

package ByteArrayIO;import java.io.ByteArrayInputStream;public class ByteArrayIOTest2 {	public static final int LENGTH = 3;	public static final byte[] datas = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,			0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,			0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A };	public static void main(String[] args) {		System.out.println("源数据为:"+new String(datas, 0, datas.length));		new ByteArrayIOTest2().test();	}	private void test() {		ByteArrayInputStream bais = new ByteArrayInputStream(datas);		int len;		//将数据源中的数据全部读出,并打印,此时pos应该与count想等		while((len = bais.read()) != -1){			System.out.print((char)len);		}		//将pos重置为0		bais.reset();		//将pos向后跳跃5个字节		bais.skip(5);		//将此处做上标记,下次reset时,pos定位在标记处,这里的参数0无实际意义		bais.mark(0);		System.out.println("\r\n"+(char)bais.read());		bais.skip(10);		System.out.println((char)bais.read());		bais.reset();		System.out.println((char)bais.read());	}}

同样,ByteAarrayInputStream在流关闭时,也不会影响方法的执行,不会抛出异常,并且数据仍然存在。

 

 

转载于:https://www.cnblogs.com/moonfish1994/p/10222432.html

你可能感兴趣的文章
UIPickView之自定义生日键盘和城市键盘
查看>>
改变 C/C++ 控制台程序的输出颜色和样式
查看>>
第1章 游戏之乐——让CPU占用率曲线听你指挥
查看>>
laravel入门教程
查看>>
整理大数据期末考试复习提纲--概念整理
查看>>
线程--promise furture 同步
查看>>
Mybatis3.2.3+mysql第一个例子(入门)
查看>>
Nginx 代理配置
查看>>
跟锦数学171217-180630
查看>>
Python之random
查看>>
【IE大叔开玩笑】之——CSS设置IE6中容器高度的BUG
查看>>
转,python的匿名函数lambda解释及用法
查看>>
与FPGA相关的独热码
查看>>
systemd(CentOS7)启动zookeeper
查看>>
测试相关
查看>>
java.lang.ClassCastException: com.sun.proxy.$Proxy0 cannot be cast to java.sql.Connection异常问题解决...
查看>>
[CQOI 2018]社交网络
查看>>
HTML5基础总结
查看>>
Android Studio开发入门-引用jar及so文件
查看>>
ADO constants include file for VBScript
查看>>