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


    文章最后有完整测试代码

    基本代码如下:(代码注释部分不用看,一步步学习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=======================================


    CSDN博客地址:https://blog.csdn.net/qq_34115899
  • 相关阅读:
    ASP.NET之Application、Session和Cookie的差别
    Android 最火高速开发框架AndroidAnnotations使用具体解释
    关于牛逼的顺丰--也谈管理
    SIFT特征提取分析
    [置顶] 网页提交方式post和get的区别和联系
    xcode 5.0 以上去掉icon高亮方法&amp;iOS5白图标问题
    我是怎样成长为系统架构师的
    怎样使用oracle 的DBMS_SQLTUNE package 来执行 Sql Tuning Advisor 进行sql 自己主动调优
    UDP用户数据报协议和IP分组
    使用Java高速实现进度条
  • 原文地址:https://www.cnblogs.com/lcy0515/p/9215097.html
Copyright © 2020-2023  润新知