首页 技术 正文
技术 2022年11月22日
0 收藏 850 点赞 2,609 浏览 3720 个字

1. ByteArrayInputStream

定义


继承了InputStream,数据源是内置的byte数组buf,那read ()方法的使命(读取一个个字节出来),在ByteArrayInputStream就是简单的通过定向的取buf元素实现的

核心源码理解


源码:

 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;
}

理解:

1. 构造ByteArrayInputStream, 直接将外部的byte数组作为内置的buf,作为被读取的数据源

源码:

     // 存放数据的地方
protected byte buf[]; // 下一个要被读取的位置,即等待读取的位置
protected int pos; // 标记pos的位置
protected int mark = 0; // 实际能被读取的byte的数量
protected int count;

理解:

源码:

public synchronized int read() { return (pos < count) ? (buf[pos++] & 0xff) : -1;}

理解:

1. 该方法是被synchronized修饰的,其它方法也是,故ByteArrayInputStream是线程安全的

2. byte类型和0xff做与运算,转成byte的无符号类型(0-255),上节也说明过

源码:

 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;
}

理解:

  1. 因为数据源是byte数组,目的源也是byte数组,故直接采用了数组copy的方法,写入到b数组中

源码:

 public synchronized long skip(long n) {
long k = count - pos;
if (n < k) {
k = n < 0 ? 0 : n;
} pos += k;
return k;
}

理解:

  1. 通过调整pos的值,来实现skip操作

源码:

public void close() throws IOException { }

理解:

  1. 空实现,故close后并不会有任何影响,还是可以继续往外读的

2. ByteArrayOutputStream

定义


继承了OutputStream,目的源是内置的byte数组buf,write()方法是一个个字节写入到buf中(其实就是简单到buf[i]=b,这种赋值操作)

核心源码理解


源码:

 // 目的源,存储数据的地方
protected byte buf[]; // buf中实际的byte数(不是buf.length)
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];
}

理解:

  1. 默认构造ByteArrayOutputStream的buf长度是32;可以指定存储数据的buf数组的长度

源码:

 public synchronized void write(int b) {
ensureCapacity(count + 1);
buf[count] = (byte) b;
count += 1;
}

理解:

  1. 重写了InputStream的write(int b) 方法,直接给buf某个元素赋值;

  2. 被synchronized修饰(包括其它方法),因此ByteArrayOutputStream是线程安全的

  3. ensureCapacity,是判断当前的容量和buf.length的大小,如果超过了buf.length,则会对buf进行扩容(申请一个更大的数组,通过Arrays.copyOf方法进行旧元素copy,让buf指向这个新的大数组)

源码:

 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;
}

理解:

  1. 参数b数组是数据源,待被读取的字节数组,由于目的源是内置的字节数组buf,直接通过数组copy的形式完成写入操作

  2. 与ByteArrayInputStream的read(byte b[], int off, int len)几乎一样,只是内置的buf数组和参数b数组的数据源角色和目的源角色互调下而已

源码:

public synchronized byte toByteArray()[] { return Arrays.copyOf(buf, 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);
}

理解:

  1. 这三个方法都是取出内置的buf数据,比较容易理解

源码:

public void close() throws IOException {  }

理解:

  1. close后还是可以继续写入的

3. 总结:

1. 实现了mark与reset方法,mark方法中让mark=pos,reset时让pos=mark,比较容易理解

4. 问题:

1. 欢迎大家提出问题,共同交流学习!

5. 示例:

     /**
* ByteArrayInputStream的read是从自己内置的buf中读,read的数据源是buf
* ByteArrayOutputStream的write是写入到自己内置的buf中去,write的目的源是buf
*/
public static void test1() {
// 对应abcddefghijklmnopqrsttuvwxyz的ASCII码十六进制分别为
byte[] bytes = new byte[] { 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
}; // 0x64, 0x65, 0x66, 0x67, 0x68
ByteArrayInputStream bis = new ByteArrayInputStream(bytes, 3, 5);
ByteArrayOutputStream bos = new ByteArrayOutputStream(); //默认内置的buf长度为32哦
int b = 0;
while((b = bis.read()) != -1) {
System.out.println("ASCII码的十进制: " + b); //将读到的字节,再写入到bos中的内置buf中
bos.write(b);
} // 虽然close都是空实现,但养成一个关闭资源(比如流,连接)的习惯
try {
bis.close();
bos.close();
} catch (IOException e) {
e.printStackTrace();
} System.out.println("bos的内置buf数据: " + bos.toString());
}

执行:

 public static void main(String args[]) {
test1();
}

结果:

ASCII码的十进制: 100
ASCII码的十进制: 101
ASCII码的十进制: 102
ASCII码的十进制: 103
ASCII码的十进制: 104
bos的内置buf数据: defgh

6. 参考:

1. http://www.cnblogs.com/skywang12345/p/io_03.html

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,999
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,511
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,357
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,140
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,770
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,848