简谈 ByteArrayOutputStream 和 BufferOutputStream

本文探讨在Android微信分享图片时遇到的问题,由于SDK接口变更,需将URL转换为Bitmap。通过Java IO流,特别是ByteArrayOutputStream和BufferOutputStream实现此功能。BufferOutputStream作为缓冲流减少频繁IO操作,提高性能,而ByteArrayOutputStream用于快速扩容和获取byte数组。DMA在IO中的作用也进行了简要说明。

最近在做微信分享时,发现android端sdk内置的url传递图片分享形式失效了【对应的api已经从sdk中移除了】

对于上面提到的图片分享的解决方案有两种: 一种是外界统一传bitmap到sdk内分享,一种是sdk内部解析外界传入的url然后

再传。【这里为了方便以后扩展提供了内置url转bitmap的方式】

对应url转bitmap这里采用了 java原生的输入输出流方式处理,URL-InputStream-ByteArrayOutputStream-BufferOutputStream

【代码后期补上】

这里只提:BufferOutputStream和ByteArrayOutputStream 

new ByteArrayOutputStream() 后 扔到BufferOutputStream的构造中,先通过BufferOutputStream 缓冲buffer数组缓冲(待会再谈buffer在java io流中的意义)

在InputStream和OutputStream流中调用write写数据时,不管io流采用装饰者还是适配者等设计模式,怎样去使用最终都会转换成一个一个的数据流形式进行数据读写

而对于包装了ByteArrayOutputStream的BufferOutputStream,起到的作用和ByteArrayOutputStream不同,对应的使用场景是缓冲数据,并最终对接输出流,减少频繁io带来的性能损耗。而ByteArrayOutputStream则起到快速扩容和copy array的作用,通过空间换时间将目标byte[] copy 到缓存中,最终我们需要用到的是该类的 toByteArray 得到从InputStream的byte[] 形式的bitmap

另外前面提到的buffer的作用:cpu管理所有总线,而频繁的io需要cpu去频繁确认io的操作执行,构建buffer会采用DMA【direct memory access 直接内存交互】,而DMA存在的意义在于分担cpu在频繁io中的压力,cpu在开启DMA时会传递控制参数,DMA启用时会向cpu发起dma请求,cpu让出总线管理权到dma,再由dma完成最终的数据读写,最终再根据数据的读写状态回传信息到cpu(成功失败),交回总线控制权

ps:DMA请求优先级高于中断指令,cpu会优先响应DMA请求保证内存中buffer的数据正常读写

参考

DMA数据传输简介:

https://blog.youkuaiyun.com/a675311/article/details/49274739

ByteArrayOutputStream和BufferOutputStream的详细对比:

https://blog.youkuaiyun.com/ohyesurright/article/details/20928755



`ByteArrayOutputStream` 是 Java 标准库中的一个类,位于 `java.io` 包下。它实现了一个输出,数据被写入到一个字节数组中。随着数据的不断写入,数组会自动增长。以下是关于它的使用方法、特性及示例代码: ### 特性 - **内存操作**:`ByteArrayOutputStream` 主要用于在内存中操作字节数据,而不是将数据直接写入到文件或者网络中。这使得它非常适合临时存储数据,或者在数据传输前对数据进行处理。 - **自动扩展**:随着数据的不断写入,内部的字节数组会自动扩展以容纳更多的数据,无需手动管理数组的大小。 - **数据可获取**:可以通过 `toByteArray()` 方法获取写入的所有字节数据,也可以通过 `toString()` 方法将字节数据转换为字符串。 ### 使用方法 - **创建对象**:可以直接通过无参构造函数创建一个 `ByteArrayOutputStream` 对象,也可以指定初始的缓冲区大小。 ```java // 创建一个默认大小的 ByteArrayOutputStream ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 创建一个指定初始大小的 ByteArrayOutputStream ByteArrayOutputStream baosWithSize = new ByteArrayOutputStream(1024); ``` - **写入数据**:可以使用 `write(int b)` 方法写入单个字节,或者使用 `write(byte[] b, int off, int len)` 方法写入字节数组的一部分。 ```java // 写入单个字节 baos.write(65); // 写入字符 'A' 的 ASCII 码 // 写入字节数组 byte[] data = "Hello, World!".getBytes(); baos.write(data, 0, data.length); ``` - **获取数据**:可以使用 `toByteArray()` 方法获取写入的所有字节数据,或者使用 `toString()` 方法将字节数据转换为字符串。 ```java // 获取字节数组 byte[] resultBytes = baos.toByteArray(); // 将字节数据转换为字符串 String resultString = baos.toString(); ``` - **关闭**:`ByteArrayOutputStream` 不需要显式关闭,因为它不涉及底层的资源(如文件或网络连接)。但是,在使用完后可以调用 `close()` 方法,该方法实际上不执行任何操作。 ```java baos.close(); ``` ### 示例代码 ```java import java.io.ByteArrayOutputStream; import java.io.IOException; public class ByteArrayOutputStreamExample { public static void main(String[] args) { try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { // 写入单个字节 baos.write(65); // 写入字符 'A' 的 ASCII 码 // 写入字节数组 byte[] data = "Hello, World!".getBytes(); baos.write(data, 0, data.length); // 获取字节数组 byte[] resultBytes = baos.toByteArray(); System.out.println("Byte array length: " + resultBytes.length); // 将字节数据转换为字符串 String resultString = baos.toString(); System.out.println("String result: " + resultString); } catch (IOException e) { e.printStackTrace(); } } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值