io流(文件流的重复读取)

场景

传统的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;
}
经验分享 程序员 微信小程序 职场和发展