文章最后有完整测试代码

基本代码如下:(代码注释部分不用看,一步步学习SequenceInputStream用的)

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.Vector;

public class Demo1_SequenceInputStream {
    public static void main(String[] args) throws IOException {
        // demo1();
        // demo2();
        // 名字可以改的简单点
        long time1 = System.currentTimeMillis();
        BufferedInputStream bis1 = new BufferedInputStream(new FileInputStream("F:\\歌曲串烧测试\\百石元 (hyakkoku hajime) - 楽しいねぇ (真开心呢).mp3"));
        
        BufferedInputStream bis2 = new BufferedInputStream(new FileInputStream("F:\\歌曲串烧测试\\李袁杰 - 离人愁.mp3"));
        
        BufferedInputStream bis3 = new BufferedInputStream(new FileInputStream("F:\\歌曲串烧测试\\菊池俊輔 (きくち しゅんすけ) - ドラえも~ん!.mp3"));
        
        BufferedInputStream bis4 = new BufferedInputStream(new FileInputStream("F:\\歌曲串烧测试\\纳豆nado - 红昭愿.mp3"));
        Vector<InputStream> v = new Vector<>();
        v.add(bis1);
        v.add(bis2);
        v.add(bis3);
        v.add(bis4);
        Enumeration<InputStream> en = v.elements();
        SequenceInputStream sis = new SequenceInputStream(en);
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:\\歌曲串烧测试\\测试串烧.mp3"));
        int b;
        while ((b = sis.read()) != -1) {
            bos.write(b);
        }
        sis.close();
        bos.close();
        long time2 = System.currentTimeMillis();
        System.out.println("时间:" + (time2 - time1) + "ms");
        
    }
    /*
    private static void demo2() throws FileNotFoundException, IOException {
        FileInputStream fis1 = new FileInputStream("a.txt");
        FileInputStream fis2 = new FileInputStream("b.txt");
        SequenceInputStream sis = new SequenceInputStream(fis1, fis2);
        FileOutputStream fos = new FileOutputStream("c.txt");
        int b;
        while ((b = sis.read()) != -1) {
            fos.write(b);
        }
        sis.close();
        fos.close();
    }

    private static void demo1() throws FileNotFoundException, IOException {
        FileInputStream fis1 = new FileInputStream("a.txt");

        FileOutputStream fos = new FileOutputStream("c.txt");

        int b1;
        while ((b1 = fis1.read()) != -1) {
            fos.write(b1);
        }
        fis1.close();
        FileInputStream fis2 = new FileInputStream("b.txt");
        int b2;
        while ((b2 = fis2.read()) != -1) {
            fos.write(b2);
        }
        fis2.close();
        fos.close();
    }*/
}

一共12.9M,测试数据如下:

如果输入流输出流都不用Bufferedxxxx包装,需要76xxxms,大约76s

如果输出流不用BufferedOutputStream包装,输入流用BufferedInputStream包装,需要37xxxms,大约37s

如果输入流不用BufferedInputStream包装,输出流用BufferedOutputStream包装,需要34xxxms,大约34s

如果输入流用BufferedInputStream包装,输出流用BufferedOutputStream包装,需要496ms,大约0.5s

歌曲都可以正常播放!


        SequenceInputStream 表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。

还有一个问题了,为什么我的bis1, bis2, bis3, bis4没有关闭?是不是我忘了?

没忘!!!

先大致看一下构造方法


SequenceInputStream类的成员变量InputStream in;默认为null


第一次就在构造方法里面nextStream()执行到in = (InputStream) e.nextElement();获取到in是第一个bufferedInputstream流对象bis1,然后外面方法执行到while循环

 while ((b = sis.read()) != -1) {
            fos.write(b);
  }

以下是SequenceInputStream的read()


可以看到里面有int c = in.read();此时就是BufferedInputStream类的read(),先从文件读取8192字节,再从内存一个个读取(详情见我的另一篇转载博客深入理解BufferedInputStream实现原理),然后if (c != -1)就返回读到的字符,也就是第一个流执行完成后才会执行nextStream(); 执行下一个流时nextStream()方法会判断if (in != null) {in.close();},也就是每个流执行完之后继续执行下一个流时,上一个流就已经关闭了。再继续看到nextStream()方法,依次往下执行,直到最后一个流读取完成return -1;整个流才算读完了。

然后再关闭SequenceInputStream流,也就是sis.close();


其实刚刚已经关了bis1, bis2, bis3了,只剩下bis4了,此刻执行到nextStream的第一个if时会把bis4也关掉,然后in=null;返回---出循环。

所以输入流就已经全部关闭了,不用冗余的写bis1, bis2, bis3, bis4去close()了。

===================================================================

完整测试代码:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.Vector;

public class Test {
    static SequenceInputStream sis;
    static BufferedReader br;

    public static void main(String[] args) throws IOException {
        br = new BufferedReader(new InputStreamReader(System.in, "gbk"));
        System.out.println("请输入第一首歌曲路径:");
        Vector<InputStream> v = new Vector<>();
        File f = getFile(); // 确认正确的路径
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));
        v.add(bis);
        while (true) {
            System.out.println("是否继续添加下一首歌曲? Y/N");
            String s = br.readLine();
            if (s.equalsIgnoreCase("Y")) {
                System.out.println("下一首歌路径:");
                BufferedInputStream Bis = new BufferedInputStream(new FileInputStream(getFile()));
                v.add(Bis);
            } else if (s.equalsIgnoreCase("N")) {
                break;
            } else {
                System.out.println("输入有误!");
            }
        }
        System.out.println("请输入生成的歌曲路径:");
        Enumeration<InputStream> en = v.elements();  
        SequenceInputStream sis = new SequenceInputStream(en);
        File f1 = createFile();
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(f1));
        
        br.close();
        long time1 = System.currentTimeMillis();
        int b;
        while ((b = sis.read()) != -1) {
            bos.write(b);
        }
        long time2 = System.currentTimeMillis();
        sis.close();
        bos.close();
        System.out.println("成功生成文件:" + f1.getName());
        System.out.println("文件路径:" + f1.getAbsolutePath());
        System.out.println("执行时间:" + (time2 - time1) + "ms");
    }

    private static File createFile() throws IOException {
        File f = new File(br.readLine());
        if (f.isDirectory()) {
            return new File(f, "默认生成歌曲名.mp3");
        }
        return f;
    }

    private static File getFile() throws IOException {
        File f;
        while (true) {
            f = new File(br.readLine());
            if (!f.exists()) {
                System.out.println("您输入的文件不存在,请重新输入!");
            } else if (f.isDirectory()) {
                System.out.println("您输入的是文件夹,请重新输入!");
            } else {
                return f;
            }
        }
    }
}




========================================Talk is cheap, show me the code=======================================