A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© WakeUp 中级黑马   /  2014-11-4 00:26  /  1096 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 WakeUp 于 2014-11-5 20:07 编辑

我们知道合并流SequenceInputStream可以将多个流合并到一起,RandomAccessFile可以设置指针指向要操作的数据位置,我的想法是,将一部电影切割若干碎片文件,分别用合并流和RandomAccessFile将这些碎片进行合并,其中RandomAccessFile使用多线程技术,每个线程负责一个碎片,多个线程同时写入一个文件中,比较合并流和RandomAccessFile两者的速度,于是有了如下代码:
  1. package com.itheima;
  2. /*
  3. 需求:
  4. 将一部视频切割成若干碎片文件,每个文件100M大小
  5. 然后用两种方法将这些碎片文件重新合并
  6. 第一种方法:合并流SequenceInputStream
  7. 第二种方法:RandomAccessFile
  8. 比较两种方法合并文件所用的时间

  9. 结论:
  10. 合并流:5913ms
  11. Random:18174ms
  12. */
  13. import java.io.*;
  14. import java.util.*;
  15. public class CompMergeFiles{
  16.         
  17.         public static void main(String[] args) throws Exception{
  18.                
  19.                 //File file = new File("F:\\java\\碟中谍:幽灵协议.rmvb");
  20.                 //int num = splitFile(file);

  21.                 long start1 = System.currentTimeMillis();
  22.                 mergeFiles_1(7);
  23.                 long end1 = System.currentTimeMillis();
  24.                 System.out.println("Sequence times:"+(end1-start1)+"ms");

  25.                 long start2 = System.currentTimeMillis();
  26.                 mergeFiles_2(7);
  27.                 long end2 = System.currentTimeMillis();
  28.                 System.out.println("Random times:"+(end2-start2)+"ms");
  29.                
  30.         }
  31.         
  32.         public static int splitFile(File file) throws IOException{
  33.                
  34.                 FileInputStream fis = new FileInputStream(file);
  35.                 BufferedInputStream bufis = new BufferedInputStream(fis);//关联源文件

  36.                 byte[] buf = new byte[1024*1024];
  37.                 int len = 0,count = 0;
  38.                 File partFile = new File("f:\\java\\"+(++count)+".part");//定义目标文件
  39.                 while ((len=bufis.read(buf))!=-1){
  40.                         if (partFile.length()>=1024*1024*100)//如果切割的碎片文件大于100M就新建一个文件
  41.                                 partFile = new File("f:\\java\\"+(++count)+".part");

  42.                         BufferedOutputStream bufos =
  43.                                         new BufferedOutputStream(new FileOutputStream(partFile,true));
  44.                         bufos.write(buf,0,len);
  45.                         bufos.close();
  46.                         
  47.                 }
  48.                 bufis.close();
  49.                 return count;
  50.         }

  51.         //第一种合并文件的方法:SequenceInputStream
  52.         public static void mergeFiles_1(int num) throws IOException{
  53.                
  54.                 ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();//集合用于存放读取流对象
  55.                 for (int x=1;x<=num ;x++ ){
  56.                         al.add(new FileInputStream("f:\\java\\"+x+".part"));
  57.                 }

  58.                 final Iterator<FileInputStream> it = al.iterator();
  59.                 //匿名内部类,Enumeration接口对象,重写接口中的方法
  60.                 Enumeration<FileInputStream> en = new Enumeration<FileInputStream>(){
  61.                         public boolean hasMoreElements(){
  62.                                 return it.hasNext();
  63.                         }
  64.                         public FileInputStream nextElement(){
  65.                                 return it.next();
  66.                         }
  67.                 };

  68.                 SequenceInputStream sis = new SequenceInputStream(en);//建立合并流对象,将Enumeration对象传入
  69.                 BufferedOutputStream bufos =
  70.                                 new BufferedOutputStream(new FileOutputStream("f:\\java\\01.rmvb"));

  71.                 byte[] buf = new byte[1024*1024];
  72.                 int len = 0;
  73.                 while ((len=sis.read(buf))!=-1){
  74.                         bufos.write(buf,0,len);
  75.                         bufos.flush();
  76.                 }
  77.                 sis.close();
  78.                 bufos.close();
  79.         }

  80.         //第二种方法合并文件:RandomAccessFile
  81.         public static void mergeFiles_2(int num) throws Exception{
  82.                
  83.                 RandomAccessFile raf = new RandomAccessFile("f:\\java\\02.rmvb","rw");//关联写入文件
  84.                 Thread[] t = new Thread[num];//定义线程数组,大小为碎片数目
  85.                 for (int x=1;x<=num ;x++ ){
  86.                         t[x-1] = new Thread(new RandomMergeFile(x,raf));
  87.                         t[x-1].start();//启动线程
  88.                         t[x-1].join();//让主程序等待该线程结束
  89.                 }
  90.                 raf.close();//等到所有线程结束后关闭资源
  91.         }

  92. }

  93. //定义一个类,用来封装向文件中写入数据的功能,该类实现了多线程
  94. class RandomMergeFile implements Runnable{
  95.         
  96.         private int x = 0;//定义要读取的文件号码
  97.         private RandomAccessFile raf = null;//用于接收RandomAccessFile的引用
  98.         RandomMergeFile(int x,RandomAccessFile raf){
  99.                 this.x = x;
  100.                 this.raf = raf;
  101.         }
  102.         public void run(){
  103.                 try{
  104.                         BufferedInputStream bufis =
  105.                                         new BufferedInputStream(new FileInputStream("f:\\java\\"+x+".part"));//读取碎片文件

  106.                         byte[] buf = new byte[1024];
  107.                         int len = 0;
  108.                         raf.seek((x-1)*1024*1024*100L);//设置指针位置,按100M大小存储文件
  109.                         while ((len=bufis.read(buf))!=-1){               
  110.                                 raf.write(buf,0,len);
  111.                         }
  112.                         bufis.close();

  113.                 }
  114.                 catch (IOException e){
  115.                         System.out.println(e);
  116.                 }        
  117.         }
  118. }

复制代码
结果就是合并流要比RandomAccessFile要快,那么问题来了,多线程的操作应该要比单线程的合并流要快,为什么结果却是合并流速度快?不知道各位运行的情况如何。



0 个回复

您需要登录后才可以回帖 登录 | 加入黑马