功能简介

 
ByteArrayInputStream 和 ByteArrayOutputStream
提供了针对于字符数组 byte [] 的标准的IO操作方式
 
 
ByteArrayInputStream将会给一个byte buf[]   提供标准的IO操作方式
 
ByteArrayOutputStream则是将数据写入到内部的字节数组中
 
 

ByteArrayInputStream 详解

功能: 从提供的字节数组中,以IO的行为方式工作,进行读取数据
 

ByteArrayInputStream字段

protected byte[] buf 用于保存由该流的创建者提供的 byte 数组
也就是构造方法传入
protected int count 个数
protected int mark 流中当前的标记位置
构造时默认将 ByteArrayInputStream 对象标记在位置零处
通过 mark() 方法可将其标记在缓冲区内的另一个位置处
通过 reset() 方法将当前缓冲区位置设置为此点
protected int mark = 0;定义时设置了默认值,如果不设置将为0
protected int pos 要从输入流缓冲区中读取的下一个字符的索引
 
 

ByteArrayInputStream构造方法

public ByteArrayInputStream(byte[] buf) 需要传入byte buf[] 字节数组作为他的缓冲区
当前起始下标 pos  为0
count为数组长度
mark位置为0

public ByteArrayInputStream(byte[] buf,
                            int offset,
                            int length)
传入字节数组以及偏移量和长度
当前起始下标 pos  为 指定的偏移量
个数为offset+length 和 buf.length中小的那个
mark为偏移量起始地址
可以理解为,这个字节数组偏移量的部分才是数据源,前面都没关系

 
 

read方法

读取下一个位置的字节
如果下一个位置 pos小于总个数
返回pos下标的字节数组数据
并且pos自增
& 0xff  :
Java中只有  有符号数,类型提升时是按照符号位扩展的
对于正数,没有什么影响
对于负数,按照符号位扩展和按照0位扩展区别很大

按符号位扩展,也就是补符号位,值不变
按零位扩展,也就是补零时,相当于有符号数转变为无符号数

所以在数值计算中,直接使用类型提升,数值不变
而对于编解码时,需要进行转换

&0xff这种方式就是来确保是按补零扩展
0xff默认为int型,是十六进制,十进制中表示为255,二进制为32位,后八位为'1111 1111',其他24位均为0
a & 0xff 操作时,因为a为byte型,所以会将a自动转化为int型(高位补1)
byte & 0xff操作一般将byte数据转换成int型,最终的数据只有低8位有数据,其他位为0

简单说就是读取pos下标的元素,返回值为int
  
 
带参数的read()方法
将数据读取到b的off位置处

//从流中读取数据到b[] 中,从off开始写,写len长度

public synchronized int read(byte b[], int off, int len) {

if (b == null) {//如果b为null 空指针

throw new NullPointerException();

} else if (off < 0 || len < 0 || len > b.length - off) {//如果偏移量小于0 或者写入长度小于0 或者想要读取的长度小于实际的长度了

throw new IndexOutOfBoundsException();

}

if (pos >= count) {//如果位置光标已经到了最后了,没有数据可读,返回-1

return -1;

}

int avail = count - pos;//可用个数为总个数count - 当前位置pos

if (len > avail) {//如果想要读取的len比实际拥有的数据要长,那么只读取实际的个数

len = avail;

}

if (len <= 0) {

return 0;

}

System.arraycopy(buf, pos, b, off, len);//使用本地方法拷贝数据 buf 的pos位置开始拷贝,拷贝len个,到b的off位置

pos += len;//位置光标后移

return len;

}

 
read方法本质很简单
就是一个数组,读取一个,就光标移动下一个,pos就是记住位置的变量
读取的就是指定下标的元素
 

skip

 
 

available

本质就是个数组,所以可用个数就是总个数减去下一个字符的索引
 
 

mark /markSupported /reset

ByteArrayInputStream支持mark和reset
而且 很显然,mark方法的输入参数是无效的
何处调用,何处就是标记点
调用reset就是pos设置到标记点
为什么mark 的参数无效?
很显然,ByteArrayInputStream是操作字符数组的,而且,这个数组不是复制而来的
是直接通过引用指向的
也就是说整个的字节数组都在随时可访问的范围内,要这个参数有什么用呢
mark /markSupported /reset 三连的本质在于提供可重复读的功能,所以对于不可逆的流需要缓存
此处天然自带可以随时读取某个下标的能力
 

close

 
ByteArrayInputStream的根本在于针对给定的某个字节数组,提供IO操作方式的统一形式
就好像你写了个方法操作字节数组一样,完全不涉及资源
所以无需关闭任何实质内容
通过close关闭ByteArrayInputStream之后,如果再次使用这个流
并不会抛出异常
当然,流结束了,就不能再继续使用了
 
所有方法列表
 
 
 

ByteArrayOutputStream详解

 
以IO的行为方式工作,将数据写入到内部的字节数组中
 

ByteArrayOutputStream字段

protected byte buf[]; 存储数据的缓冲区
protected int count; 缓冲区中的有效字节数,每次写入将会写入到buf[count]处
 
 

ByteArrayOutputStream构造方法

 
构造方法只是设置内部字节数组这个缓冲区数据的大小
    public ByteArrayOutputStream() ;
默认长度为32位
public ByteArrayOutputStream(int size) 只要参数值合法,创建指定个数的字节数组缓冲区
 
 
 

write

write是输出,参数都是他的输出内容,只是不同的流输出的目的不一样,此处我们的输出流的目的地是内部的字节数组
write(int) 将指定的字节写入此 byte 数组输出流
也就是写入到内部的字节数组中
write(byte[], int, int) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此 byte 数组输出流
也就是写入到内部的字节数组中
 
可以看得出来,他们都有使用 ensureCapacity在必要的时候进行扩展
扩展的行为是新建一个更大的,然后将原有数组元素全部拷贝过去
保证空间足够的情况下
write(int)  就是buf[count] = (byte)b;
对于write(byte[], int, int)  则是使用System.arraycopy
 

writeTo(OutputStream)

 
因为ByteArrayOutputStream内部维护的是一个字节数组,所以可以直接作为OutputStream中write()方法的参数
代码很简单,就是讲内部的字节数组,转存到入参指定的输出流中
相当于把流中的数据重写了一份到另外的输出流
 

toString()

计算机所有的数据都是二进制存储,最小的单位是字节,字符的编码形式也正是字节
所以,toString其实就是把字节序列进行解码

  
int类型入参的方法,在JDK1.8  已经弃用
toString()使用平台默认的字符集,通过解码字节将缓冲区内容转换为字符串

toString(String charsetName)   使用指定的 charsetName,通过解码字节将缓冲区内容转换为字符串
 
 

 

reset()

reset是重置的意思,ByteArrayOutputStream 使用buf[] 存储数据,使用count指示位置
所以想要重新使用现在的缓冲区,抛弃原来所有的,只需要将count清零,每次的数据重新从0开始写入字节数组即可
反正我们知道现在总共有多少有效字节,原来写入到buf中的可能多于count的那些字节就放着好了,我们也不去使用
 

size()

count就是一直用来记录有效个数的,所以直接返回count就是实际的size
 
 

toByteArray()

转换为字节数组,它本身就是一个字节数组
所以转换比较简单,只需要创建一个大小相同的字节数组,并且将数据拷贝过去即可
 

close()

ByteArrayOutputStream 写入的是自己内部的字节数组
属于内存数据,不涉及任何资源,所以close不需要做什么
 
 
 
 
 
 
 
 
 
 
 
 
 
 

[六]JavaIO之 ByteArrayInputStream与ByteArrayOutputStream的更多相关文章

  1. FileInputstream,FileOutputstream 和 byteArrayInputStream,byteArrayOutputStream

    你知道FileInputstream和FileOutputstream吗?FileInputstream,FileOutputstream分别是由抽象类Inputstream和Outputstream ...

  2. Java IO(七)ByteArrayInputStream 和 ByteArrayOutputStream

    Java IO(七)ByteArrayInputStream 和 ByteArrayOutputStream 一.介绍 ByteArrayInputStream 和 ByteArrayOutputSt ...

  3. Java IO流学习总结六:ByteArrayInputStream、ByteArrayOutputStream

    类的继承关系 InputStream |__ ByteArrayInputStream OutputStream |__ ByteArrayOutputStream ByteArrayInputStr ...

  4. [二十六]JavaIO之再回首恍然(如梦? 大悟?)

    流分类回顾 本文是JavaIO告一段落的总结帖 希望对JavaIO做一个基础性的总结(不涉及NIO) 从实现的角度进行简单的介绍 下面的这两个表格,之前出现过 数据源形式 InputStream Ou ...

  5. ByteArrayInputStream和ByteArrayOutputStream

    public class ByteArrayTest { public static void main(String[] args) throws IOException { read(write( ...

  6. ByteArrayInputStream 和 ByteArrayOutputStream

    package java.io; /** * A <code>ByteArrayInputStream</code> contains * an internal buffer ...

  7. 黑马程序猿 IO流 ByteArrayInputStream与ByteArrayOutputStream

    ---------------------- ASP.Net+Unity开发..Net培训.期待与您交流! ---------------------- package cn.itcast.IO; i ...

  8. Java之IO(三)ByteArrayInputStream和ByteArrayOutputStream

    转载请注明源出处:http://www.cnblogs.com/lighten/p/6972297.html 1.前言 这组输入输出流比较特殊,一般的流指定都是磁盘IO和网络IO,从文件中读取数据或者 ...

  9. java io流 数据流 DataInputStream、DataOutputStream、ByteArrayInputStream、ByteArrayOutputStream

    例子程序: package io; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import ...

随机推荐

  1. C#三目运算符

    在编写项目的时候,会经常用到 if else 判断语句,但有些简单的判断或赋值,可以通过三目运算符来完成! 例如: int sex=0; string sexText=""; if ...

  2. 20175324 《Java程序设计》第七周学习总结

    教材学习内容总结 常用实用类 String类 - 程序可以直接使用String类,但不能进行扩展,即String类不可以有子类 - 常用构造方法 - String(char a[])用一个字符数组a创 ...

  3. cadence布线完成后的补充操作

    完成布线之后,需要生成光绘文件和钻孔文件,在生成钻孔文件之前,还有几点补充!

  4. Windows下SQLMAP的安装图解

    第一步:BurpSuite扫描工具安装 //来源:http://www.mamicode.com/info-detail-563355.html Burp Suite 是用于渗透测试web 应用程序的 ...

  5. QEMU KVM Libvirt(12): Live Migration

    由于KVM的架构为 Libvirt –> qemu –> KVM 所以对于live migration有两种方式,一种是qemu + KVM自己的方式,一种是libvirt的方式,当然li ...

  6. QEMU KVM Libvirt手册(8): 半虚拟化设备virtio

    KVM本身并不提供半虚拟化功能,是通过virtio来实现的 The benefits of virtio drivers are of lower overhead and higher perfor ...

  7. iOS依赖库管理工具之Carthage

    在iOS开发中,我们常会用CocoaPods来进行依赖库的管理.CoaoaPods 是一套整体解决方案,我们在 Podfile 中指定好我们需要的第三方库,然后 CocoaPods 就会进行下载,集成 ...

  8. [WEB]绕过安全狗与360PHP一句话的编写

    00x01安全狗的确是让人很头痛,尤其是在上传一句话或者写入一句话的时候,会被安全狗拦截从而拿不下shell.当然,安全狗是最简单的一款waf,很容易就进行一个绕过.00x02对于绕过安全狗跟360, ...

  9. oracle 分析函数和开窗函数

    最近遇到一个需求,将查询出的数据按照地区分组,随机取出每个区域的2条数据,这里用到了oracle的分析和开窗函数: 最终写出的sql如下: select * from (select region,r ...

  10. JAVA设计模式—观察者模式和Reactor反应堆模式

    被观察者(主题)接口 定义主题对象接口 /**抽象主题角色: 这个主题对象在状态上发生变化时,会通知所有观察者对象 也叫事件对象 */ public interface Subject { //增加一 ...