文章最后有完整测试代码
基本代码如下:(代码注释部分不用看,一步步学习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=======================================