概述
在实际的工作当中,某些场合下我们常常会需要多次读取一个InputStream的需求,比如:从流中提取文本、文档格式转换、文件复制移动等。
但InputStream具有不可重复使用的特性,如果第一次使用后就关闭了流,第二次使用就会报出java.io.IOException: Stream Closed的异常,如果第一次使用没有关闭流,第二次使用的时候读取到的字节数就是0,因为在InputStream读取的时候,会有一个pos指针,他指示每次读取之后下一次要读取的起始位置,当读到最后一个字符的时候,pos指针不会进行重置。
本文是对InputStream进行重复使用提供一种方案,先将InputStream缓存到一个ByteArrayOutputStream中,用的时候进行转换获取InputStream,用完后进行销毁。
**注意:**此种解决方案有一个缺点就是会存在内存压力,需要在时间和空间之间找到一个平衡点。
创建缓存工具类
package com.frame.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* 流操作过程中处理流的多次消费问题
* @author LXW
* @date 2020/6/15 20:33
*/
public class InputStreamCache {
private static final Logger logger = LoggerFactory.getLogger(InputStreamCache.class);
/**
* 将InputStream中的字节保存到ByteArrayOutputStream中。
*/
private ByteArrayOutputStream byteArrayOutputStream;
private InputStream inputStream;
public InputStreamCache(InputStream inputStream) {
if (inputStream == null) return;
this.inputStream = inputStream;
initCache();
}
/**
* 初始化
*/
private void initCache(){
byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
try {
while ((len = inputStream.read(buffer)) != -1 ) {
byteArrayOutputStream.write(buffer, 0, len);
}
byteArrayOutputStream.flush();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
/**
* 获取缓存流
* @return InputStream
*/
public InputStream getInputStream() {
if (byteArrayOutputStream == null) return this.inputStream;
return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
}
/**
* 销毁
*/
public void destroyCache() {
this.byteArrayOutputStream = null;
if(this.inputStream != null) {
try {
this.inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
流的重复使用方式
public static void main(String[] args) throws Exception {
File fileIn = new File("F:\111\test.txt");
InputStream in = new FileInputStream(fileIn);
File fileOut = new File("F:\111\test001.txt");
OutputStream out = new FileOutputStream(fileOut);
//模拟InputStream是由外部传参进入方法
getContentAndCopyFile(in,out);
}
/**
* 获取文本内容并拷贝文件
* @param in
* @param out
*/
public static void getContentAndCopyFile(InputStream in ,OutputStream out){
InputStreamCache inputStreamCache = new InputStreamCache(in);
try{
//获取文本内容
getContent(inputStreamCache.getInputStream());
//文件拷贝
copyFile(inputStreamCache.getInputStream(),out);
}catch(Exception e){
//TODO 异常处理
e.printStackTrace();
}finally {
try {
//流关闭
if(out != null){ out.close(); }
if(in != null){ in.close(); }
//销毁处理
if(inputStreamCache != null){inputStreamCache.destroyCache();}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 文件拷贝
* @param in
* @param out
*/
public static void copyFile(InputStream in ,OutputStream out){
int len;
byte[] buff = new byte[1024];
try {
while((len = in.read(buff))!= -1){
out.write(buff,0,len);
out.flush();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(out != null){ out.close(); }
if(in != null){ in.close(); }
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 获取txt文档中的文本内容
* @param in 文件流
* @return TXT文档内容
*/
public static String getContent(InputStream in) {
StringBuffer sb = new StringBuffer();
BufferedReader reader =null;
String line = null;
try {
reader = new BufferedReader(new InputStreamReader(in,"UTF-8"));
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(in != null){in.close();}
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
最后
以上就是怡然航空为你收集整理的InputStream多次重复使用的解决方案的全部内容,希望文章能够帮你解决InputStream多次重复使用的解决方案所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复