問(wèn)題描述:
在項(xiàng)目中用有個(gè)上傳功能,會(huì)把文件轉(zhuǎn)換成inputstream然后轉(zhuǎn)換成byte[] 數(shù)組
轉(zhuǎn)換代碼如下:
[java]
view plain copypublic 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;
}
根據(jù)測(cè)試,上傳一個(gè)7M的文件, 但是執(zhí)行swapStream.write(buff, 0, rc); 這段代碼的時(shí)候,一共消耗了20M的內(nèi)存,不應(yīng)該啊,內(nèi)存多么重要的東西。
問(wèn)題原因:
查看 ByteArrayOutputStream 的API得知
此類(lèi)實(shí)現(xiàn)了一個(gè)輸出流,其中的數(shù)據(jù)被寫(xiě)入一個(gè)字節(jié)數(shù)組。緩沖區(qū)會(huì)隨著數(shù)據(jù)的不斷寫(xiě)入而自動(dòng)增長(zhǎng)??墒褂?nbsp;toByteArray() 和 toString() 檢索數(shù)據(jù)。
得知一個(gè)關(guān)鍵信息,就是緩沖區(qū),查看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的時(shí)候并沒(méi)有在構(gòu)造函數(shù)制定緩沖區(qū)的大小,所以默認(rèn)是初始化32bytes,但是對(duì)于7M大的文件來(lái)說(shuō),32bytes 遠(yuǎn)遠(yuǎn)不夠,所以ByteArrayOutputStream 緩沖區(qū)會(huì)自動(dòng)增長(zhǎng),這個(gè)自動(dòng)增長(zhǎng)的過(guò)程,根據(jù)源碼來(lái)看會(huì)有copyArray動(dòng)作,所以整個(gè)write過(guò)程,消耗內(nèi)存成倍增長(zhǎng)。
源碼如下:
[java]
view plain copypublic 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;
}
解決辦法:
我是這么解決的,不知道還有沒(méi)有更好的辦法。
我們可以得到上傳文件File對(duì)象的length,在創(chuàng)建 ByteArrayOutputStream 對(duì)象的時(shí)候把length屬性放在構(gòu)造函數(shù)里面:
[java]
view plain copypublic 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;
}
最后測(cè)試結(jié)果 [java]
view plain copyswapStream.write(buff, 0, rc); 一共消耗7M內(nèi)存
若有更好的解決方案,請(qǐng)告知。