0
点赞
收藏
分享

微信扫一扫

InputStream为什么不能被重复读取?

非凡兔 2022-11-21 阅读 187


首先,熟悉Java的人可能都知道,Java中的Inputstream是不能重复读取的。 
但是有没有想过,InputStream为什么不能重复读呢? 
其实要回答“为什么”这个问题很简单,就是人家接口就是这么设计的,不能重复读。 
所以今天要讨论的问题更像是:Java的InputStream为什么要设计为不能重复读? 
关于InputStream为什么不能重复读取,网上也各有说法: 
有的同学说: 
“InputStream就类比成一个杯子,杯子里的水就像InputStream里的数据,你把杯子里的水拿出来了,杯子的水就没有了,InputStream也是同样的道理。” 
比喻的非常好,让我们从直观上认识了InputStream为什么不能重复被读。 
也有的同学从更深的代码角度去分析: 
“在InputStream读取的时候,会有一个pos指针,他指示每次读取之后下一次要读取的起始位置,当读到最后一个字符的时候,pos指针不会重置。” 
说的也有道理,就是说InputStream的读取是单向的。但是并不是所有的InputStream实现类都是这样的实现方式。


  1. //BufferedInputStream代码片段:
  2. public synchronized int read() throws
  3. if
  4.             fill();  
  5. if
  6. return -1;  
  7.         }  
  8. return getBufIfOpen()[pos++] & 0xff;  
  9.     }  
  10.   
  11. //FileInputStream代码片段:
  12. public native int read() throws

我们知道: 
Java 的List内部是使用数组实现的,遍历的时候也有一个pos指针。但是没有说List遍历一个第二次遍历就没有了。第二次遍历是创建新的Iterator,所以pos也回到了数组起始位置。对于某些InputStream当然可以也这么做。例如:ByteArrayInputStream 
ByteArrayInputStream就是将一个Java的byte数组保存到对象里,然后读取的时候遍历该byte数组。 


  1. public ByteArrayInputStream(byte
  2. this.buf = buf;  
  3. this.pos = 0;  
  4. this.count = buf.length;  
  5. }  
  6.   
  7. public synchronized int
  8. return (pos < count) ? (buf[pos++] & 0xff) : -1;  
  9. }  

就ByteArrayInputStream而言,要实现重复读取是很简单的,但是为什么没有。我想是为了遵循InputStream的统一标准。 
在InputStream的read方法的注释上明确说明: 


  1. /**
  2.      * Reads the next byte of data from the input stream. The value byte is
  3.      * returned as an <code>int</code> in the range <code>0</code> to
  4.      * <code>255</code>. If no byte is available because the end of the stream
  5.      * has been reached, the value <code>-1</code> is returned. This method
  6.      * blocks until input data is available, the end of the stream is detected,
  7.      * or an exception is thrown.
  8.      *
  9.      * <p> A subclass must provide an implementation of this method.
  10.      *
  11.      * @return     the next byte of data, or <code>-1</code> if the end of the
  12.      *             stream is reached.
  13.      * @exception  IOException  if an I/O error occurs.
  14.      */
  15. public abstract int read() throws

当流到达末尾后,返回-1. 

其实像FileInputStream这样的文件流,要实现重复使用可能也并不是很难,利用缓存什么的应该能做到(大文件读取就悲剧了,呵呵呵)。 
但是InputStream顾名思义就是一个单向的字节流,跟水流一样,要想再次使用就自己再去源头取一下。 
InputStream其实不像杯子,更像是一根水管,要想喝水了,就在把水管架在水源与杯子之间,让水流到杯子里(注意:这个动作完成了之后水管里面就没有水了)。 
这样看来,InputStream其实是一个数据通道,只负责数据的流通,并不负责数据的处理和存储等其他工作范畴。 
前面讲过,其实有的InputStream实现类是可以实现数据的处理工作的。但是没有这么做,这就是规范和标准的重要性。 

举报

相关推荐

0 条评论