inputstream java_Java实现inputstream流的复制
获取到一个inputstream后,可能要多次利用它进行read的操作。由于流读过一次就不能再读了,而InputStream对象本身不能复制,而且它也没有实现Cloneable接口,所以得想点办法。
实现思路:
1、先把InputStream转化成ByteArrayOutputStream
2、后面要使用InputStream对象时,再从ByteArrayOutputStream转化回来
代码实现如下:
package com.test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class StreamOperateUtil {
public static void main(String[] args) throws FileNotFoundException {
InputStream input = new FileInputStream("c:\\test.txt");
//InputStream input = httpconn.getInputStream(); //这里可以写你获取到的流
ByteArrayOutputStream baos = cloneInputStream(input);
// 打开两个新的输入流
InputStream stream1 = new ByteArrayInputStream(baos.toByteArray());
InputStream stream2 = new ByteArrayInputStream(baos.toByteArray());
}
private static ByteArrayOutputStream cloneInputStream(InputStream input) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = input.read(buffer)) > -1) {
baos.write(buffer, 0, len);
}
baos.flush();
return baos;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
这种适用于一些不是很大的流,因为缓存流是会消耗内存的。
关于InputStream为什么不能被重复读取?
首先,熟悉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 int
in the range 0
to
* 255
. If no byte is available because the end of the stream
* has been reached, the value -1
is returned. This method
* blocks until input data is available, the end of the stream is detected,
* or an exception is thrown.
*
*
A subclass must provide an implementation of this method.
*
* @return the next byte of data, or -1
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实现类是可以实现数据的处理工作的。但是没有这么做,这就是规范和标准的重要性。
inputstream java_Java实现inputstream流的复制相关推荐
- IO流之字节流 +字符流 (复制文件)
复制的本质,如字节流字节数组复制,根据方法.read()的一次一次2个字节的读取,第一次读出的是ab 长度 2,第二次读出cd长度2,第三次读出e 长度1,但是还没结束,第四次读出0,长度-1,结束循 ...
- Java实现流的复制,解决流不可重用问题
背景介绍 在使用Java进行流操作的过程中,会出现需要重复使用流的情况,但是InputStream接口并未实现cloneable接口,因此不能实现复制,这是就要用到把流转换为另外一种形式,然后存入内存 ...
- java inputstream长度_Java InputStream.available获取数据流字节长度大小
首页 > 基础教程 > IO流 > InputStream类 Java InputStream.available获取数据流字节长度大小 定义 public int availabl ...
- java inputstream 图片_Java InputStream读取网络图片
首页 > 基础教程 > IO流 > InputStream类 Java InputStream读取网络图片 Java从网络读取图片通过InputStream保存至本地,代码如下: p ...
- java inputstream子类_Java InputStream 类
Java InputStream 类 在本教程中,我们将通过一个示例来学习Java InputStream类及其方法. java.io包的InputStream类是一个抽象超类,它表示字节的输入流. ...
- PgSQL一主二从(流式复制)
PgSQL集群(流式复制,CentOS 7) 参考:http://blog.itpub.net/30126024/viewspace-2672741/ https://blog.csdn.net/we ...
- java 复制 inputstream_关于对inputstream流的复制
今天因为项目需要,获取到一个inputstream后,可能要多次利用它进行read的操作.由于流读过一次就不能再读了,所以得想点办法. 而InputStream对象本身不能复制,因为它没有实现Clon ...
- Android UI 之WaterFall瀑布流效果 [复制链接]
2019独角兽企业重金招聘Python工程师标准>>> 所谓瀑布流效果,简单说就是宽度相同但是高度不同的一大堆图片,分成几列,然后像水流一样向下排列,并随着用户的上下滑动自动加载更多 ...
- java 字符流图片_java 字节流、字符流(复制图片、复制文本)
1.File 1)构造方法 2)创建 3)判断.获取 4)删除 2.字节流 1)字节流写数据的3种方式 FileOutputStream fos = new FileOutputStream(&quo ...
最新文章
- 牛客--追债之旅 两种解法
- 怎么html跟asp结合,xml与asp简单结合实现html模板功能.doc
- Linux查看某个进程的线程
- 站长们都会,但是都会写错的robots!
- C语言再学习 -- 常用头文件和函数(转)
- springboot项目启动后找不到jsp文件
- BCEWithLogitsLoss的使用案例
- java hexits,[Java]浅谈Java的异常体系
- sps忘记保存文档怎么恢复_路由器管理员密码忘了怎么办【解决方法】
- 5G+AIoT“零碳”解决方案 | 模组助力“4S” 融合的新一代智能汽车驶入快车道
- web渗透中bypass防护系统
- 独家 | 利用滴滴出行数据透视中国城市空间发展(附视频PPT)
- java修改ppt模板并导出
- 车牌识别的matlab程序(程序_讲解_模板),车牌识别的matlab程序(程序-讲解-模板)资料...
- android_98_自定义DragLayout
- 中国移动为何要对手机上网流量封顶
- 主板常见故障的维修方法
- python求列表list平均值的方法
- 关于dede获取购物车中商品ID及提交为表单问题总结
- php+中文分词scws+sphinx+mysql打造千万级数据全文搜索
热门文章
- 【C语言进阶深度学习记录】五 C语言中变量的属性
- spark on yarn 部署问题
- Beta冲刺(9/7)——2019.5.31
- NOI2004郁闷的出纳员
- 145. Binary Tree Postorder Traversal
- codechef Polo the Penguin and the Tree
- [转载]Visual Studio 2010敏捷利剑:详解Scrum
- tableau地图城市数据_举个栗子!Tableau 技巧(156):在地图分析中创建缓冲区
- raid5需要几块硬盘_Raid5磁盘阵列数据恢复思路分析--附真实案例
- faker和劫的图片_faker亲手画的劫被曝光,看到他的画,众人心里久久不能平息!...