什么是 InputStream
InputStream就是Java标准库提供的最基本的输入流。它位于java.io这个包里。java.io包提供了所有同步IO的功能。
要特别注意的一点是,InputStream并不是一个接口,而是一个抽象类,它是所有输入流的超类
为什么要复用 InputStream
- 在实际的工作当中,某些场合下我们常常会需要多次读取一个InputStream的需求,比如:从流中提取文本、文档格式转换、文件复制移动等。
- 但InputStream具有不可重复使用的特性,如果第一次使用后就关闭了流,第二次使用就会报出java.io.IOException: Stream Closed的异常,如果第一次使用没有关闭流,第二次使用的时候读取到的字节数就是0,因为在InputStream读取的时候,会有一个pos指针,他指示每次读取之后下一次要读取的起始位置,当读到最后一个字符的时候,pos指针不会进行重置。
方法一【不建议使用】
先将InputStream转为string,需要用到的时候再将string转为InputStream
注意:读取excel等office文件时会损坏文件流
- 将InputStream转为string
public static String inToStr(InputStream in){
return new BufferedReader(new InputStreamReader(in)).lines().collect(Collectors.joining(System.lineSeparator()));
}
- 将string转为InputStream
public static InputStream strToIn(String str){
return new ByteArrayInputStream(str.getBytes());
}
方法二【建议使用】
转为ByteArrayInputStream,每次使用完都使用reset方法将指针指向开头
- 将InputStream转为ByteArrayInputStream
/**
1. 将InputStream转换成ByteArrayOutputStream
*/
public static ByteArrayOutputStream toOutByteStream(InputStream in) throws IOException {
ByteArrayOutputStream out =new ByteArrayOutputStream();
byte[] buffer=new byte[1024];
int len;
while((len=in.read(buffer))>-1){
out.write(buffer,0,len);
}
out.flush();
in.close();
return out;
}
/**
* InputStream转成ByteArrayInputStream
*/
public static ByteArrayInputStream toByteArrayInputStream(InputStream in) throws IOException {
return getInput(toOutByteStream(in));
}
- 重置指针
public static void reset(ByteArrayInputStream in){
if (in != null){
in.reset();
}
}
- 实际使用
public void importExcel(InputStream stream) {
ByteArrayInputStream newIn = IoUtil.toByteArrayInputStream(stream);//转为ByteArrayInputStream(有异常自己处理下)
ExcelReader reader = Excel.getReader(newIn);//获取reader
IoUtil.reset(newIn);//重置指针
List<Sheet> sheets = reader.getSheets();//获取所有sheet
for (int i = 0; i < sheets.size(); i++) {
try{
Sheet sheet = sheets.get(i);
//获取列表元素
List<ModelAtomExcelVo> datas = ExcelUtil.read(T.class,sheet.getSheetName(),newIn);
IoUtil.reset(newIn);//重置指针
System.out.println(datas);
}catch (Exception e){
log.error("", e);
}
}
//释放资源
IoUtil.close(stream,newIn)
}
小结
其中还可以将InputStream缓存起来,但是对于内存的开销会比较大,个人认为方法二已经可以满足需求了