场景
传统的io流是无法重复读取的。
但是我们经常会用到一些需要重复利用流的场景,例如上传图片并解析文件。
过程
大部分的IO流是无法重复读取的,只能读取一次,再读取时,会抛出异常,我们可以使用ByteArrayOutputStream将流数据缓存到内存中,达到多次读取的目的。
1、将不可重复的IO输入流读取到ByteArrayOutputStream中,ByteArrayOutputStream是一个可重复使用的输出流。
private ByteArrayOutputStream getBOS(InputStream in) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
BufferedInputStream br = new BufferedInputStream(in);
for(int c=0;(c=br.read())!=-1;){
bos.write(c);
}
br.close();
} catch (Exception e) {
logger.error("",e);
}
return bos;
}
2、生成一个新的可重复读取的InputStream
这个时候的bis是可以被多次重复读取,close对其无效,但是要注意每次读前,调用bis.reset();方法需要将游标重置到流的头部。
InputStream bis = new ByteArrayInputStream(bos.toByteArray());
尝试代码
读写一次,内容正确。代码:
public static void main(String[] args) throws Exception{
String fileName="in.txt";
String outFileName="out.txt";
try {
FileInputStream in = new FileInputStream("d://" + fileName);
FileOutputStream out = new FileOutputStream("d://" + outFileName);
for(int c=0;(c=in.read())!=-1;){
out.write(c);
}
out.close();
in.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
读之后写2次,第二次写为空(out2.txt没内容),因为常规文件流不能复用。代码:
public static void main(String[] args) throws Exception{
String fileName="in.txt";
String outFileName="out.txt";
String outFileName2="out2.txt";
try {
FileInputStream in = new FileInputStream("d://" + fileName);
FileOutputStream out = new FileOutputStream("d://" + outFileName);
FileOutputStream out2 = new FileOutputStream("d://" + outFileName2);
// out的写入
for(int c=0;(c=in.read())!=-1;){
out.write(c);
}
// out2的写入
for(int c=0;(c=in.read())!=-1;){
out2.write(c);
}
out.close();
out2.close();
in.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
使用可复用的文件流,2次写入均成功:
public static void main(String[] args) throws Exception{
String fileName="in.txt";
String outFileName="out.txt";
String outFileName2="out2.txt";
try {
FileInputStream fileInputStream = new FileInputStream("d://" + fileName);
InputStream in = new ByteArrayInputStream(getBOS(fileInputStream).toByteArray());
FileOutputStream out = new FileOutputStream("d://" + outFileName);
FileOutputStream out2 = new FileOutputStream("d://" + outFileName2);
// out的写入
for(int c=0;(c=in.read())!=-1;){
out.write(c);
}
in.reset();
// out2的写入
for(int c=0;(c=in.read())!=-1;){
out2.write(c);
}
out.close();
out2.close();
in.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
private static ByteArrayOutputStream getBOS(InputStream in) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
BufferedInputStream br = new BufferedInputStream(in);
for(int c=0;(c=br.read())!=-1;){
bos.write(c);
}
br.close();
} catch (Exception e) {
logger.error("",e);
}
return bos;
}