前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >用java实现歌曲串烧高速版(SequenceInputStream的使用)

用java实现歌曲串烧高速版(SequenceInputStream的使用)

作者头像
砖业洋__
发布2023-05-06 17:15:55
2440
发布2023-05-06 17:15:55
举报
文章被收录于专栏:博客迁移同步

文章最后有完整测试代码

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

代码语言:javascript
复制
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循环

代码语言:javascript
复制
 while ((b = sis.read()) != -1) {
            fos.write(b);
  }

以下是SequenceInputStream的read()

可以看到里面有int c = in.read();此时就是BufferedInputStream类的read(),先从文件读取8192字节,再从内存一个个读取,然后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()了。

完整测试代码:

代码语言:javascript
复制
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;
            }
        }
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-06-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
腾讯云服务器利旧
云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档