-
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
-
-
-
-
-
public
ByteArrayOutputStream() {
-
this
(
32
);
-
}
我使用ByteArrayOutputStream的时候并没有在构造函数制定缓冲区的大小,所以默认是初始化32bytes,但是对于7M大的文件来说,32bytes 远远不够,所以
ByteArrayOutputStream 缓冲区会自动增长,这个自动增长的过程,根据源码来看会有copyArray动作,所以整个write过程,消耗内存成倍增长。
源码如下:
-
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
-
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
问题描述:在项目中用有个上传功能,会把文件转换成inputstream然后转换成byte[] 数组转换代码如下:[java] view plain copypublic static byte[] convertstream(InputStream inStream) throws IOException { ByteArr
此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 to
ByteArray
() 和 toString() 获取数据。
关闭
ByteArray
OutputStream
无效。此类中的
方法
在关闭此流后仍可被调用,而不会产生任何
IO
Except
io
n。
2.构造
方法
ByteArray
OutputStream
()
内存
操作流一般在生成一些临时信息时会使用,如果将临时信息保存到文件中,则代码
执行
完后需再删除文件,此时使用
内存
操作流更合适。
ByteArray
InputStream 主要完成将内容写入到
内存
中,而
ByteArray
OutputStream
主要将
内存
中的数据输出。
public class
ByteArray
Demo {
public static void main(String[] a...
public void downloadFile(File file,HttpServletResponse response,boolean isDelete) {
try {
// 以流的形式下载文件。
BufferedInputStream fis = new BufferedInputStream(new FileInputStream(file.getPath()));
OutputSt...
ByteArray
OutputStream
:
内存
流的输出流
ByteArray
InputStream:
内存
流的输入流,它是唯一一种能够直接从网络上获取二进制数据的流
CharArrayReader:
内存
流中的输入流
CharArray
Write
r:
内存
流中的输出流
ByteArr...
这个错误通常是因为你的上传
方法
需要使用 `FileInputStream` 类型的对象作为参数,而你却传入了一个 `
ByteArray
InputStream` 类型的对象,导致类型转换错误。
如果你需要上传一个文件,建议使用 `FileInputStream` 类型对象来读取该文件。你可以使用 `FileInputStream` 类来打开文件,然后读取该文件的内容。例如:
File file = new File("path/to/your/file");
InputStream inputStream = new FileInputStream(file);
// 将 inputStream 传递给上传
方法
如果你已经有了一个 `
ByteArray
InputStream` 类型的对象,你可以考虑使用 `
ByteArray
OutputStream
` 类来将其转换成 `FileInputStream` 类型。例如:
ByteArray
InputStream bais = new
ByteArray
InputStream(your
ByteArray
);
ByteArray
OutputStream
baos = new
ByteArray
OutputStream
();
byte[] buffer = new byte[1024];
int len;
while ((len = bais.read(buffer)) > -1 ) {
baos.
write
(buffer, 0, len);
baos.flush();
InputStream inputStream = new
ByteArray
InputStream(baos.to
ByteArray
());
// 将 inputStream 传递给上传
方法
注意,在使用 `
ByteArray
OutputStream
` 将 `
ByteArray
InputStream` 转换成 `FileInputStream` 时,需要将 `
ByteArray
InputStream` 中的数据先读取到 `
ByteArray
OutputStream
` 中,再将 `
ByteArray
OutputStream
` 转换成 `FileInputStream`。