java IO笔记(ByteArrayInputStream/ByteArrayOutputStream)

25 篇文章 0 订阅

今天讲的是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;

public
class 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在流关闭时,也不会影响方法的执行,不会抛出异常,并且数据仍然存在。











  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
ByteArrayInputStreamByteArrayOutputStreamJava中的两个字节类。ByteArrayOutputStream类在创建实例时会创建一个内部的byte数组缓冲区,可以向该缓冲区写入byte类型的数据。而ByteArrayInputStream类则包含一个内部的缓冲区,用于存储从中读取的字节数据。这两个类可以方便地用于在内存中读取和写入字节数据。 通过ByteArrayOutputStream类,我们可以将多个变量的数据收集到一起,然后一次性将数据发送出去。具体使用方法如下: 1. 创建一个ByteArrayOutputStream对象。 2. 创建一个DataOutputStream对象,将其与ByteArrayOutputStream对象关联。 3. 使用DataOutputStream对象的方法将数据写入ByteArrayOutputStream对象。 4. 调用ByteArrayOutputStream对象的toByteArray()方法,将数据转换为字节数组。 通过ByteArrayInputStream类,我们可以从字节数组中读取数据。具体使用方法如下: 1. 创建一个ByteArrayInputStream对象,将其与字节数组关联。 2. 创建一个DataInputStream对象,将其与ByteArrayInputStream对象关联。 3. 使用DataInputStream对象的方法从ByteArrayInputStream对象中读取数据。 这样,我们就可以方便地使用DataOutputStream和DataInputStream封装的方法来读取和写入字节数组中的数据。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* *2* *3* [ByteArrayOutputStreamByteArrayInputStream详解](https://blog.csdn.net/iteye_15544/article/details/82069753)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

moonfish0607

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值