1. public static byte [] convertstream(InputStream inStream) throws IOException {
  2. ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
  3. byte [] buff = new byte [ 10240 ];
  4. int rc = 0 ;
  5. while ((rc = inStream.read(buff, 0 , 10240 )) > 0 ) {
  6. swapStream.write(buff, 0 , rc);
  7. }
  8. byte [] buf = swapStream.toByteArray();
  9. swapStream.close();
  10. return buf;
  11. }
根据测试,上传一个7M的文件, 但是执行swapStream.write(buff, 0, rc); 这段代码的时候,一共消耗了20M的内存,不应该啊,内存多么重要的东西。

问题原因:

查看 ByteArrayOutputStream 的API得知

此类实现了一个输出流,其中的数据被写入一个字节数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() toString() 检索数据。

得知一个关键信息,就是缓冲区,查看ByteArrayOutputStream 源代码如下:

[java] view plain
  1. /**
  2. * Creates a new byte array output stream. The buffer capacity is
  3. * initially 32 bytes, though its size increases if necessary.
  4. */
  5. public ByteArrayOutputStream() {
  6. this ( 32 );
  7. }
我使用ByteArrayOutputStream的时候并没有在构造函数制定缓冲区的大小,所以默认是初始化32bytes,但是对于7M大的文件来说,32bytes 远远不够,所以

ByteArrayOutputStream 缓冲区会自动增长,这个自动增长的过程,根据源码来看会有copyArray动作,所以整个write过程,消耗内存成倍增长。

源码如下:

  1. public synchronized void write( byte b[], int off, int len) {
  2. if ((off < 0 ) || (off > b.length) || (len < 0 ) ||
  3. ((off + len) > b.length) || ((off + len) < 0 )) {
  4. throw new IndexOutOfBoundsException();
  5. } else if (len == 0 ) {
  6. return ;
  7. }
  8. int newcount = count + len;
  9. if (newcount > buf.length) {
  10. buf = Arrays.copyOf(buf, Math.max(buf.length << 1 , newcount));
  11. }
  12. System.arraycopy(b, off, buf, count, len);
  13. count = newcount;
  14. }

解决办法:

我是这么解决的,不知道还有没有更好的办法。

我们可以得到上传文件File对象的length,在创建 ByteArrayOutputStream 对象的时候把length属性放在构造函数里面:

[java] view plain
  1. public static byte [] convertstream(InputStream inStream, long length) throws IOException {
  2. length = length > Integer.MAX_VALUE ? Integer.MAX_VALUE : length;
  3. ByteArrayOutputStream swapStream = new ByteArrayOutputStream(( int )length);
  4. byte [] buff = new byte [ 10240 ];
  5. int rc = 0 ;
  6. while ((rc = inStream.read(buff, 0 , 10240 )) > 0 ) {
  7. swapStream.write(buff, 0 , rc);
  8. }
  9. byte [] buf = swapStream.toByteArray();
  10. swapStream.close();
  11. return buf;
  12. }
最后测试结果 [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`。