本帖最后由 WakeUp 于 2014-11-5 20:07 编辑
我们知道合并流SequenceInputStream可以将多个流合并到一起,RandomAccessFile可以设置指针指向要操作的数据位置,我的想法是,将一部电影切割若干碎片文件,分别用合并流和RandomAccessFile将这些碎片进行合并,其中RandomAccessFile使用多线程技术,每个线程负责一个碎片,多个线程同时写入一个文件中,比较合并流和RandomAccessFile两者的速度,于是有了如下代码:
- package com.itheima;
- /*
- 需求:
- 将一部视频切割成若干碎片文件,每个文件100M大小
- 然后用两种方法将这些碎片文件重新合并
- 第一种方法:合并流SequenceInputStream
- 第二种方法:RandomAccessFile
- 比较两种方法合并文件所用的时间
- 结论:
- 合并流:5913ms
- Random:18174ms
- */
- import java.io.*;
- import java.util.*;
- public class CompMergeFiles{
-
- public static void main(String[] args) throws Exception{
-
- //File file = new File("F:\\java\\碟中谍:幽灵协议.rmvb");
- //int num = splitFile(file);
- long start1 = System.currentTimeMillis();
- mergeFiles_1(7);
- long end1 = System.currentTimeMillis();
- System.out.println("Sequence times:"+(end1-start1)+"ms");
- long start2 = System.currentTimeMillis();
- mergeFiles_2(7);
- long end2 = System.currentTimeMillis();
- System.out.println("Random times:"+(end2-start2)+"ms");
-
- }
-
- public static int splitFile(File file) throws IOException{
-
- FileInputStream fis = new FileInputStream(file);
- BufferedInputStream bufis = new BufferedInputStream(fis);//关联源文件
- byte[] buf = new byte[1024*1024];
- int len = 0,count = 0;
- File partFile = new File("f:\\java\\"+(++count)+".part");//定义目标文件
- while ((len=bufis.read(buf))!=-1){
- if (partFile.length()>=1024*1024*100)//如果切割的碎片文件大于100M就新建一个文件
- partFile = new File("f:\\java\\"+(++count)+".part");
- BufferedOutputStream bufos =
- new BufferedOutputStream(new FileOutputStream(partFile,true));
- bufos.write(buf,0,len);
- bufos.close();
-
- }
- bufis.close();
- return count;
- }
- //第一种合并文件的方法:SequenceInputStream
- public static void mergeFiles_1(int num) throws IOException{
-
- ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();//集合用于存放读取流对象
- for (int x=1;x<=num ;x++ ){
- al.add(new FileInputStream("f:\\java\\"+x+".part"));
- }
- final Iterator<FileInputStream> it = al.iterator();
- //匿名内部类,Enumeration接口对象,重写接口中的方法
- Enumeration<FileInputStream> en = new Enumeration<FileInputStream>(){
- public boolean hasMoreElements(){
- return it.hasNext();
- }
- public FileInputStream nextElement(){
- return it.next();
- }
- };
- SequenceInputStream sis = new SequenceInputStream(en);//建立合并流对象,将Enumeration对象传入
- BufferedOutputStream bufos =
- new BufferedOutputStream(new FileOutputStream("f:\\java\\01.rmvb"));
- byte[] buf = new byte[1024*1024];
- int len = 0;
- while ((len=sis.read(buf))!=-1){
- bufos.write(buf,0,len);
- bufos.flush();
- }
- sis.close();
- bufos.close();
- }
- //第二种方法合并文件:RandomAccessFile
- public static void mergeFiles_2(int num) throws Exception{
-
- RandomAccessFile raf = new RandomAccessFile("f:\\java\\02.rmvb","rw");//关联写入文件
- Thread[] t = new Thread[num];//定义线程数组,大小为碎片数目
- for (int x=1;x<=num ;x++ ){
- t[x-1] = new Thread(new RandomMergeFile(x,raf));
- t[x-1].start();//启动线程
- t[x-1].join();//让主程序等待该线程结束
- }
- raf.close();//等到所有线程结束后关闭资源
- }
- }
- //定义一个类,用来封装向文件中写入数据的功能,该类实现了多线程
- class RandomMergeFile implements Runnable{
-
- private int x = 0;//定义要读取的文件号码
- private RandomAccessFile raf = null;//用于接收RandomAccessFile的引用
- RandomMergeFile(int x,RandomAccessFile raf){
- this.x = x;
- this.raf = raf;
- }
- public void run(){
- try{
- BufferedInputStream bufis =
- new BufferedInputStream(new FileInputStream("f:\\java\\"+x+".part"));//读取碎片文件
- byte[] buf = new byte[1024];
- int len = 0;
- raf.seek((x-1)*1024*1024*100L);//设置指针位置,按100M大小存储文件
- while ((len=bufis.read(buf))!=-1){
- raf.write(buf,0,len);
- }
- bufis.close();
- }
- catch (IOException e){
- System.out.println(e);
- }
- }
- }
复制代码 结果就是合并流要比RandomAccessFile要快,那么问题来了,多线程的操作应该要比单线程的合并流要快,为什么结果却是合并流速度快?不知道各位运行的情况如何。
|
|