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