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

2024-02-16 00:08

本文主要是介绍InputStream为什么不能被重复读取?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

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




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

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


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

Java代码   收藏代码
  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 IOException;  


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

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

这篇关于InputStream为什么不能被重复读取?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/712944

相关文章

poj2406(连续重复子串)

题意:判断串s是不是str^n,求str的最大长度。 解题思路:kmp可解,后缀数组的倍增算法超时。next[i]表示在第i位匹配失败后,自动跳转到next[i],所以1到next[n]这个串 等于 n-next[n]+1到n这个串。 代码如下; #include<iostream>#include<algorithm>#include<stdio.h>#include<math.

poj3261(可重复k次的最长子串)

题意:可重复k次的最长子串 解题思路:求所有区间[x,x+k-1]中的最小值的最大值。求sa时间复杂度Nlog(N),求最值时间复杂度N*N,但实际复杂度很低。题目数据也比较水,不然估计过不了。 代码入下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring

pip-tools:打造可重复、可控的 Python 开发环境,解决依赖关系,让代码更稳定

在 Python 开发中,管理依赖关系是一项繁琐且容易出错的任务。手动更新依赖版本、处理冲突、确保一致性等等,都可能让开发者感到头疼。而 pip-tools 为开发者提供了一套稳定可靠的解决方案。 什么是 pip-tools? pip-tools 是一组命令行工具,旨在简化 Python 依赖关系的管理,确保项目环境的稳定性和可重复性。它主要包含两个核心工具:pip-compile 和 pip

matlab读取NC文件(含group)

matlab读取NC文件(含group): NC文件数据结构: 代码: % 打开 NetCDF 文件filename = 'your_file.nc'; % 替换为你的文件名% 使用 netcdf.open 函数打开文件ncid = netcdf.open(filename, 'NC_NOWRITE');% 查看文件中的组% 假设我们想读取名为 "group1" 的组groupName

学习记录:js算法(二十八):删除排序链表中的重复元素、删除排序链表中的重复元素II

文章目录 删除排序链表中的重复元素我的思路解法一:循环解法二:递归 网上思路 删除排序链表中的重复元素 II我的思路网上思路 总结 删除排序链表中的重复元素 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。 图一 图二 示例 1:(图一)输入:head = [1,1,2]输出:[1,2]示例 2:(图

C# 防止按钮botton重复“点击”的方法

在使用C#的按钮控件的时候,经常我们想如果出现了多次点击的时候只让其在执行的时候只响应一次。这个时候很多人可能会想到使用Enable=false, 但是实际情况是还是会被多次触发,因为C#采用的是消息队列机制,这个时候我们只需要在Enable = true 之前加一句 Application.DoEvents();就能达到防止重复点击的问题。 private void btnGenerateSh

解决Office Word不能切换中文输入

我们在使用WORD的时可能会经常碰到WORD中无法输入中文的情况。因为,虽然我们安装了搜狗输入法,但是到我们在WORD中使用搜狗的输入法的切换中英文的按键的时候会发现根本没有效果,无法将输入法切换成中文的。下面我就介绍一下如何在WORD中把搜狗输入法切换到中文。

【经验交流】修复系统事件查看器启动不能时出现的4201错误

方法1,取得『%SystemRoot%\LogFiles』文件夹和『%SystemRoot%\System32\wbem』文件夹的权限(包括这两个文件夹的所有子文件夹的权限),简单点说,就是使你当前的帐户拥有这两个文件夹以及它们的子文件夹的绝对控制权限。这是最简单的方法,不少老外说,这样一弄,倒是解决了问题。不过对我的系统,没用; 方法2,以不带网络的安全模式启动,运行命令行,输入“ne

MySQL脏读、不可重复读、幻读(虚读)

事务的特性: 原子性:指处于同一个事务中的多条语句是不可分割的。一致性:事务必须使数据库从一个一致性状态变换到另外一个一致性状态。比如转账,转账前两个账户余额之和为2k,转账之后也应该是2K。隔离性:指多线程环境下,一个线程中的事务不能被其他线程中的事务打扰持久性:事务一旦提交,就应该被永久保存起来。 事务隔离性问题: 如果不考虑事务的隔离性,会出现以下问题: 脏读:指一个线程中的事务读取到

argodb自定义函数读取hdfs文件的注意点,避免FileSystem已关闭异常

一、问题描述 一位同学反馈,他写的argo存过中调用了一个自定义函数,函数会加载hdfs上的一个文件,但有些节点会报FileSystem closed异常,同时有时任务会成功,有时会失败。 二、问题分析 argodb的计算引擎是基于spark的定制化引擎,对于自定义函数的调用跟hive on spark的是一致的。udf要通过反射生成实例,然后迭代调用evaluate。通过代码分析,udf在