打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
执行java.io.ByteArrayOutputStream.write 方法内存突然加大的原因与解决办法
问题描述:
在项目中用有个上传功能,会把文件转换成inputstream然后转换成byte[] 数组
转换代码如下:
[java] view plain copy
public static byte[] convertstream(InputStream inStream) throws IOException {
ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
byte[] buff = new byte[10240];
int rc = 0;
while ((rc = inStream.read(buff, 0, 10240)) > 0) {
swapStream.write(buff, 0, rc);
}
byte[] buf = swapStream.toByteArray();
swapStream.close();
return buf;
}
根据测试,上传一个7M的文件, 但是执行swapStream.write(buff, 0, rc); 这段代码的时候,一共消耗了20M的内存,不应该啊,内存多么重要的东西。
问题原因:
查看 ByteArrayOutputStream 的API得知
此类实现了一个输出流,其中的数据被写入一个字节数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() 和 toString() 检索数据。
得知一个关键信息,就是缓冲区,查看ByteArrayOutputStream 源代码如下:
[java] view plain copy
/**
* Creates a new byte array output stream. The buffer capacity is
* initially 32 bytes, though its size increases if necessary.
*/
public ByteArrayOutputStream() {
this(32);
}
我使用ByteArrayOutputStream的时候并没有在构造函数制定缓冲区的大小,所以默认是初始化32bytes,但是对于7M大的文件来说,32bytes 远远不够,所以ByteArrayOutputStream 缓冲区会自动增长,这个自动增长的过程,根据源码来看会有copyArray动作,所以整个write过程,消耗内存成倍增长。
源码如下:
[java] view plain copy
public synchronized void write(byte b[], int off, int len) {
if ((off < 0) || (off > b.length) || (len < 0) ||
((off + len) > b.length) || ((off + len) < 0)) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return;
}
int newcount = count + len;
if (newcount > buf.length) {
buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount));
}
System.arraycopy(b, off, buf, count, len);
count = newcount;
}
解决办法:
我是这么解决的,不知道还有没有更好的办法。
我们可以得到上传文件File对象的length,在创建 ByteArrayOutputStream 对象的时候把length属性放在构造函数里面:
[java] view plain copy
public static byte[] convertstream(InputStream inStream, long length) throws IOException {
length = length > Integer.MAX_VALUE ? Integer.MAX_VALUE : length;
ByteArrayOutputStream swapStream = new ByteArrayOutputStream((int)length);
byte[] buff = new byte[10240];
int rc = 0;
while ((rc = inStream.read(buff, 0, 10240)) > 0) {
swapStream.write(buff, 0, rc);
}
byte[] buf = swapStream.toByteArray();
swapStream.close();
return buf;
}
最后测试结果 [java] view plain copy
swapStream.write(buff, 0, rc); 一共消耗7M内存
若有更好的解决方案,请告知。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
Java解析网络数据流的三种特殊方法
ByteArrayOutputStream和ByteArrayInputStream详解
java使用socket文件上传
JAVA NIO之浅谈内存映射文件原理与DirectMemory
net实现压缩功能
值类型与引用类型的区别
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服