黑马程序员技术交流社区
标题:
关于SequenceInputStream和RandomAccessFile
[打印本页]
作者:
WakeUp
时间:
2014-11-4 00:26
标题:
关于SequenceInputStream和RandomAccessFile
本帖最后由 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要快,那么问题来了,多线程的操作应该要比单线程的合并流要快,为什么结果却是合并流速度快?不知道各位运行的情况如何。
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2