引用:之前在做项目的时候遇到一个问题,就是从网络上读取的图片要上传到oss,图片要裁剪压缩。上传和裁剪都使用了图片的inputStream,由于inputstream不能重复读取,导致裁剪成功上传失败。我们今天提供两种方法来解决inputStream无法重复读取的问题。问题分析:inputStream内部有一个pos指针,读指针的时候会一直往前走,走到尽头就不能再读了。下面写个简单的例子看看:Stringtext="TestinputStreamcontent";InputStreaminputStream=newByteArrayInputStream(text.getBytes());byte[]readArray=newbyte[inputStream.available()];intreadCount1=inputStream.read(readArray);System.out.println("read"+readCount1+"bytes");byte[]readArray2=newbyte[inputStream.available()];intreadCount2=inputStream.read(readArray2);System.out.println("read"+readCount2+"bytes");/***执行结果为*Read23bytes*Read-1byte*/从执行结果可以看出inputstream的设计只能读取一次。注意:这里稍微提一下inputStream.available()方法,本地文件可以直接知道文件大小,但是如果是网络中的数据,最好不要用这个方法,因为传输不是连续的,数据的大小就会不准确。问题解决:那么在我们实际的项目中,应该如何解决呢?你不能真的只使用一次inputSteam。下面看解决方法:方法一:使用ByteArrayOutputStream缓存字节,然后每次从缓存中读取ByteArrayOutputStr从eam拿走。很自然的想到缓存inputStream(当然不是说一定要放在ByteArrayOutputStream中,其他的方法也是可以的,都是缓存的思路,有很多实现方式,这个比较方便)Stringtext="测试输入流内容";InputStreamrawInputStream=newByteArrayInputStream(text.getBytes());ByteArrayOutputStreamoutputStream=newByteArrayOutputStream();字节[]缓冲区=新字节[1024];国际长度;while((len=raw.InputStreamread(buffer))>-1){outputStream.write(buffer,0,len);}outputStream.flush();InputStreamin1=newByteArrayInputStream(outputStream.toByteArray());InputStreamin2=newByteArrayInputStream(outputStream.toByteArray());intreadCount1=in1.read(缓冲区);intreadCount2=in2.read(缓冲区);System.out.println("read"+readCount1+"bytes");System.out.println("read"+readCount2+"bytes");/***执行结果是*读23个字节*读23个字节*这里是读取inputStream的数据先输出,然后当我们要重复使用inputStream中的内容时,再输出ut里面的数据取出来(很神奇的设置,output可以重复取,input只能读一次)方法二:其实inputStream里面有操作指针的方法,mark和reset,mark一下就知道了并通过听名字重置。在使用inputSteam之前,我们标记了inputStream指针的位置。读完后,重新设置一下,就可以重复使用了。我们看代码:Stringtext="TestinputStreamcontent";InputStreamrawInputStream=newByteArrayInputStream(text.getBytes());byte[]readArray=newbyte[1024];rawInputStream.mark(0);intreadCount1=rawInputStream.read(readArray);rawInputStream.reset();intreadCount2=rawInputStream.read(readArray);系统输出。println("read"+readCount1+"bytes");System.out.println("read"+readCount2+"bytes");总结:1.inputStream只能读取一次,也就是只能调用一次read()或其他带参数的read()方法,下次调用时读取的值为-1。在做项目的时候不要忘记这一点,这可能会导致一些陷阱;2.是使用cache或者mark/reset方法来复用inputStream。这里需要注意的是,如果inputStream的内容很多,缓存不是一个好办法,因为在用完之前会占用很多内存(这个我遇到过,上传很多图片然后就是acache,导致内存不足一直fullGC,然后CPU先爆);3.还有一个小点就是不要忘记关闭使用过的inputStream/outputSteam。
