`
该用户名已经存在
  • 浏览: 306485 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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

    博客分类:
  • Java
阅读更多
首先,熟悉Java的人可能都知道,Java中的Inputstream是不能重复读取的。
但是有没有想过,InputStream为什么不能重复读呢?
其实要回答“为什么”这个问题很简单,就是人家接口就是这么设计的,不能重复读。
所以今天要讨论的问题更像是:Java的InputStream为什么要设计为不能重复读?
关于InputStream为什么不能重复读取,网上也各有说法:
有的同学说:
“InputStream就类比成一个杯子,杯子里的水就像InputStream里的数据,你把杯子里的水拿出来了,杯子的水就没有了,InputStream也是同样的道理。”
比喻的非常好,让我们从直观上认识了InputStream为什么不能重复被读。
也有的同学从更深的代码角度去分析:
“在InputStream读取的时候,会有一个pos指针,他指示每次读取之后下一次要读取的起始位置,当读到最后一个字符的时候,pos指针不会重置。”
说的也有道理,就是说InputStream的读取是单向的。但是并不是所有的InputStream实现类都是这样的实现方式。
//BufferedInputStream代码片段:
 public synchronized int read() throws IOException {
        if (pos >= count) {
            fill();
            if (pos >= count)
                return -1;
        }
        return getBufIfOpen()[pos++] & 0xff;
    }

//FileInputStream代码片段:
public native int read() throws IOException;



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

public synchronized int read() {
        return (pos < count) ? (buf[pos++] & 0xff) : -1;
}

就ByteArrayInputStream而言,要实现重复读取是很简单的,但是为什么没有。我想是为了遵循InputStream的统一标准。
在InputStream的read方法的注释上明确说明:
/**
     * Reads the next byte of data from the input stream. The value byte is
     * returned as an <code>int</code> in the range <code>0</code> to
     * <code>255</code>. If no byte is available because the end of the stream
     * has been reached, the value <code>-1</code> is returned. This method
     * blocks until input data is available, the end of the stream is detected,
     * or an exception is thrown.
     *
     * <p> A subclass must provide an implementation of this method.
     *
     * @return     the next byte of data, or <code>-1</code> if the end of the
     *             stream is reached.
     * @exception  IOException  if an I/O error occurs.
     */
    public abstract int read() throws IOException;

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

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

相关推荐

    springboot 解决InputStream只能读取一次的问题

    springboot 解决InputStream只能读取一次的问题

    Excel POI读取封装(文件+示范代码)

    Excel POI读取封装(文件+示范代码) package org.excel.service; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java....

    超级有影响力霸气的Java面试题大全文档

    Java Bean实际上相当于微软COM模型中的本地进程内COM组件,它是不能被跨进程访问的。Enterprise Java Bean 相当于DCOM,即分布式组件。它是基于Java的远程方法调用(RMI)技术的,所以EJB可以被远程访问(跨进程、跨...

    java-servlet-api.doc

    当一个Servlet被卸载时,引擎将不能给Servlet发送任何请求。引擎必须释放Servlet并完成无用存储单元的收集 Servlet映射技术\r 作为一个Servlet引擎的开发者,你必须对于如何映射客户端的请求到Servlet有大量的适应...

    java 面试题 总结

    Java Bean实际上相当于微软COM模型中的本地进程内COM组件,它是不能被跨进程访问的。Enterprise Java Bean 相当于DCOM,即分布式组件。它是基于Java的远程方法调用(RMI)技术的,所以EJB可以被远程访问(跨进程、跨...

    JAVA上百实例源码以及开源项目

     Java 3DMenu 界面源码,有人说用到游戏中不错,其实平时我信编写Java应用程序时候也能用到吧,不一定非要局限于游戏吧,RES、SRC资源都有,都在压缩包内。 Java zip压缩包查看程序源码 1个目标文件 摘要:Java源码...

    Thinking in Java 中文第四版+习题答案

    5.2.3 private:不能接触 5.2.4 protected:“友好的一种” 5.3 接口与实现 5.4 类访问 5.5 总结 5.6 练习 第6章 类再生 6.1 合成的语法 6.2 继承的语法 6.2.1 初始化基础类 6.3 合成与继承的结合 6.3.1 确保正确的...

    Think in Java(中文版)chm格式

    5.2.3 private:不能接触 5.2.4 protected:“友好的一种” 5.3 接口与实现 5.4 类访问 5.5 总结 5.6 练习 第6章 类再生 6.1 合成的语法 6.2 继承的语法 6.2.1 初始化基础类 6.3 合成与继承的结合 ...

    JAVA_Thinking in Java

    5.2.3 private:不能接触 5.2.4 protected:“友好的一种” 5.3 接口与实现 5.4 类访问 5.5 总结 5.6 练习 第6章 类再生 6.1 合成的语法 6.2 继承的语法 6.2.1 初始化基础类 6.3 合成与继承的结合 6.3.1 确保正确的...

    Java初学者入门教学

    5.2.3 private:不能接触 5.2.4 protected:“友好的一种” 5.3 接口与实现 5.4 类访问 5.5 总结 5.6 练习 第6章 类再生 6.1 合成的语法 6.2 继承的语法 6.2.1 初始化基础类 6.3 合成与继承的结合 6.3.1 确保正确的...

    ThinkInJava

    5.2.3 private:不能接触 5.2.4 protected:“友好的一种” 5.3 接口与实现 5.4 类访问 5.5 总结 5.6 练习 第6章 类再生 6.1 合成的语法 6.2 继承的语法 6.2.1 初始化基础类 6.3 合成与继承的结合 6.3.1 确保正确的...

    java 编程入门思考

    5.2.3 private:不能接触 5.2.4 protected:“友好的一种” 5.3 接口与实现 5.4 类访问 5.5 总结 5.6 练习 第6章 类再生 6.1 合成的语法 6.2 继承的语法 6.2.1 初始化基础类 6.3 合成与继承的结合 6.3.1 确保正确的...

    thinkinjava

    5.2.3 private:不能接触 5.2.4 protected:“友好的一种” 5.3 接口与实现 5.4 类访问 5.5 总结 5.6 练习 第6章 类再生 6.1 合成的语法 6.2 继承的语法 6.2.1 初始化基础类 6.3 合成与继承的结合 6.3.1 确保正确的...

    java联想(中文)

    5.2.3 private:不能接触 5.2.4 protected:“友好的一种” 5.3 接口与实现 5.4 类访问 5.5 总结 5.6 练习 第6章 类再生 6.1 合成的语法 6.2 继承的语法 6.2.1 初始化基础类 6.3 合成与继承的结合 6.3.1 确保正确的...

    Thinking in Java简体中文(全)

    5.2.3 private:不能接触 5.2.4 protected:“友好的一种” 5.3 接口与实现 5.4 类访问 5.5 总结 5.6 练习 第6章 类再生 6.1 合成的语法 6.2 继承的语法 6.2.1 初始化基础类 6.3 合成与继承的结合 6.3.1 确保正确的...

    Thinking in Java(中文版 由yyc,spirit整理).chm

    5.2.3 private:不能接触 5.2.4 protected:“友好的一种” 5.3 接口与实现 5.4 类访问 5.5 总结 5.6 练习 第6章 类再生 6.1 合成的语法 6.2 继承的语法 6.2.1 初始化基础类 6.3 合成与继承的结合 6.3.1 确保正确的...

    JAVA_Thinking in Java(中文版 由yyc,spirit整理).chm

    5.2.3 private:不能接触 5.2.4 protected:“友好的一种” 5.3 接口与实现 5.4 类访问 5.5 总结 5.6 练习 第6章 类再生 6.1 合成的语法 6.2 继承的语法 6.2.1 初始化基础类 6.3 合成与继承的结合 6.3.1 确保正确的...

    Java JDK 7学习笔记(国内第一本Java 7,前期版本累计销量5万册)

    9.1.3 内容不重复的set 266 9.1.4 支持队列操作的queue 270 9.1.5 访问对象的iterator 273 9.1.6 排序收集的对象 276 9.1.7 使用泛型 280 9.2 键值对应的map 284 9.2.1 常用map操作类 284 9.2.2 访问...

    JAVA上百实例源码以及开源项目源代码

    Java 3DMenu 界面源码 5个目标文件 内容索引:Java源码,窗体界面,3DMenu Java 3DMenu 界面源码,有人说用到游戏中不错,其实平时我信编写Java应用程序时候也能用到吧,不一定非要局限于游戏吧,RES、SRC资源都有,都...

Global site tag (gtag.js) - Google Analytics