获取到一个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流的复制相关推荐

  1. IO流之字节流 +字符流 (复制文件)

    复制的本质,如字节流字节数组复制,根据方法.read()的一次一次2个字节的读取,第一次读出的是ab 长度 2,第二次读出cd长度2,第三次读出e 长度1,但是还没结束,第四次读出0,长度-1,结束循 ...

  2. Java实现流的复制,解决流不可重用问题

    背景介绍 在使用Java进行流操作的过程中,会出现需要重复使用流的情况,但是InputStream接口并未实现cloneable接口,因此不能实现复制,这是就要用到把流转换为另外一种形式,然后存入内存 ...

  3. java inputstream长度_Java InputStream.available获取数据流字节长度大小

    首页 > 基础教程 > IO流 > InputStream类 Java InputStream.available获取数据流字节长度大小 定义 public int availabl ...

  4. java inputstream 图片_Java InputStream读取网络图片

    首页 > 基础教程 > IO流 > InputStream类 Java InputStream读取网络图片 Java从网络读取图片通过InputStream保存至本地,代码如下: p ...

  5. java inputstream子类_Java InputStream 类

    Java InputStream 类 在本教程中,我们将通过一个示例来学习Java InputStream类及其方法. java.io包的InputStream类是一个抽象超类,它表示字节的输入流. ...

  6. PgSQL一主二从(流式复制)

    PgSQL集群(流式复制,CentOS 7) 参考:http://blog.itpub.net/30126024/viewspace-2672741/ https://blog.csdn.net/we ...

  7. java 复制 inputstream_关于对inputstream流的复制

    今天因为项目需要,获取到一个inputstream后,可能要多次利用它进行read的操作.由于流读过一次就不能再读了,所以得想点办法. 而InputStream对象本身不能复制,因为它没有实现Clon ...

  8. Android UI 之WaterFall瀑布流效果 [复制链接]

    2019独角兽企业重金招聘Python工程师标准>>> 所谓瀑布流效果,简单说就是宽度相同但是高度不同的一大堆图片,分成几列,然后像水流一样向下排列,并随着用户的上下滑动自动加载更多 ...

  9. java 字符流图片_java 字节流、字符流(复制图片、复制文本)

    1.File 1)构造方法 2)创建 3)判断.获取 4)删除 2.字节流 1)字节流写数据的3种方式 FileOutputStream fos = new FileOutputStream(&quo ...

最新文章

  1. 牛客--追债之旅 两种解法
  2. 怎么html跟asp结合,xml与asp简单结合实现html模板功能.doc
  3. Linux查看某个进程的线程
  4. 站长们都会,但是都会写错的robots!
  5. C语言再学习 -- 常用头文件和函数(转)
  6. springboot项目启动后找不到jsp文件
  7. BCEWithLogitsLoss的使用案例
  8. java hexits,[Java]浅谈Java的异常体系
  9. sps忘记保存文档怎么恢复_路由器管理员密码忘了怎么办【解决方法】
  10. 5G+AIoT“零碳”解决方案 | 模组助力“4S” 融合的新一代智能汽车驶入快车道
  11. web渗透中bypass防护系统
  12. 独家 | 利用滴滴出行数据透视中国城市空间发展(附视频PPT)
  13. java修改ppt模板并导出
  14. 车牌识别的matlab程序(程序_讲解_模板),车牌识别的matlab程序(程序-讲解-模板)资料...
  15. android_98_自定义DragLayout
  16. 中国移动为何要对手机上网流量封顶
  17. 主板常见故障的维修方法
  18. python求列表list平均值的方法
  19. 关于dede获取购物车中商品ID及提交为表单问题总结
  20. php+中文分词scws+sphinx+mysql打造千万级数据全文搜索

热门文章

  1. 【C语言进阶深度学习记录】五 C语言中变量的属性
  2. spark on yarn 部署问题
  3. Beta冲刺(9/7)——2019.5.31
  4. NOI2004郁闷的出纳员
  5. 145. Binary Tree Postorder Traversal
  6. codechef Polo the Penguin and the Tree
  7. [转载]Visual Studio 2010敏捷利剑:详解Scrum
  8. tableau地图城市数据_举个栗子!Tableau 技巧(156):在地图分析中创建缓冲区
  9. raid5需要几块硬盘_Raid5磁盘阵列数据恢复思路分析--附真实案例
  10. faker和劫的图片_faker亲手画的劫被曝光,看到他的画,众人心里久久不能平息!...