应用背景
对文件进行格式转换时如word文件转pdf文件,判断流是否为0kb,如果传入0kb的流,Aspose低版本做文件转换时会出现stackoverflow。
后端对0kb文件的判断,进行一系列处理。
解决方案
1.InputStream.available
上图为抽象类InputStream及FileInputStream类源码及注释,可以看到注释中使用estimate(估算、估计)即返回的不是真实的流的大小,而且InputStream的available方法永远返回0(The available method for class InputStream always returns 0.)。所以在业务上可以接受这个estimate
的值且不是InputStream的available方法可以使用。
2. toByteArray 转字节数组
IOUtils.toByteArray(InputStream)
转成字节数组,既然通过流拿不到大小,我就曲线救国,把流转成字节数组后,不就可以为所欲为了吗。
这么做确实拿到值了,也能准确判断其是否为空。但是你一下子把流都读成字节数组了,不觉得内存可能有些扛不住吗。
InputStream 其实就是自来水管,连着自来水厂,不管后面是一吨水,还是十吨水,这个 InputStream 占的内存都是基本固定的,用专业术语来说,它的空间复杂度是 O(1) 。 你转成字节数组的话,就相当于把十吨水全部存到你家里。数据量小还好,如果碰到大数据量或者高并发,内存一下子就撑爆了。
听我一句劝,除非你能明确评估没有 OOM 风险,否则不要转成字节数组。
3. read第一个字节
既然我们只要判断其是否为空,那我干嘛费这么大劲, InputStream 不是有 read 方法吗,我 read 一次取第一个字节不就可以判断是否为空了吗。
我们前面说过,InputStream 是自来水管,覆水难收啊,你读了一个字节,那流里就少了一个字节。这就好比有个外卖员,你问他汤咸不咸,他喝了一口,说:汤挺好的,不咸。 你拿到少了一半的汤,会是什么心情。 InputStream 虽然提供了 reset 方法,但是默认是抛异常的哦,不是所有流都可以 reset ,就像有多少爱可以重来。
4.PushbackInputStream可回退的流
PushbackInputStream
,顾名思义,就是能回退的流,你可以拿它包装一下原始的流,这样就可以实现检查流是否为空了呀。
1 | /** |
原文地址
...
...
This is copyright.