/*
* 前两个视频的弊端:在切割文件时候,不清楚切割成多少碎片文件,在合并文件时候,不清楚合并出来的是txt还是mp3还是别的
*
* 解决办法:在切割时候,用配置文件记录源文件信息
*/
package demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Properties;
public class Demo {
private static final int SIZE = 1048576;
public static void main(String[] args) throws IOException {
File file = new File("D:\\Java-Eclipse-PersonalFile\\vedio24.IO.54\\0.mp3");
splitFileDemo(file);
File dir = new File("D:\\Java-Eclipse-PersonalFile\\vedio24.IO.54");
mergeFileDemo(dir);
}
public static void splitFileDemo(File file) throws IOException {
FileInputStream fis = new FileInputStream(file);
byte[] buf = new byte[SIZE];
int len = 0;
int count = 1;
//切割文件时,必须记录注源文件(被切割文件的名称),以及记录切割成多少个碎片文件,目的是方便进行文件合并
//用键值对方式记录信息,且为了防止文件丢失,将其存于硬盘上,就用到了Properties,配置文件
Properties prop = new Properties();
FileOutputStream fos = null;
File dir = new File("D:\\Java-Eclipse-PersonalFile\\vedio24.IO.54");
if(!dir.exists())
dir.mkdirs();
while((len = fis.read(buf))!=-1){
fos = new FileOutputStream (new File(dir,(count++) + ".part"));
/*
* 【注意】count初值为1,while循环第一次,生成1.part,此时count=1+1=2;while循环第二次,生成2.part,此时count=2+1=3;
* 以此类推,所以count=碎片文件数量+1,这就是为什么mergeFileDemo里面健壮性判断会出现if(partFiles.length != (count-1))
*/
fos.write(buf,0,len);
fos.close();
}
//将被切割的文件信息存储到prop集合中
prop.setProperty("partcount", count+"");//partcount是键,对应的值是count+"",即碎片文件有count个
prop.setProperty("filename", file.getName());//存储被切割的文件名(file是该函数传进来的参数)
fos = new FileOutputStream(new File(dir,count + ".properties"));//配置文件是count.properties
//将prop集合中的数据存储到文件中
prop.store(fos, "save file info");
fos.close();
fis.close();
}
public static void mergeFileDemo(File dir) throws IOException {
//========================================================================================================
//【一】在合并文件之前,应该首先获取配置文件信息,如果有多个配置文件,那么需要过滤器;如果配置文件不存在,直接不用合并
File[] files = dir.listFiles(new SuffixFilter(".properties"));
//用listFiles()方法列举出dir中的文件,用过滤器suffixFilter过滤,拿到想要的配置文件
/**
* 健壮性判断,如果没有配置文件,说明数组file为0(不等于1),如果不止一个配置文件,说明数组file内元素个数大于1
*/
if(files.length != 1)
throw new RuntimeException(dir + "目录下没有扩展名为properties的文件或者符合条件的文件不唯一");
//获取配置文件
File configfile = files[0];
//=======================================================================================================
//【二】获取配置信息
//用读取流关联配置文件
FileInputStream fis = new FileInputStream(configfile);
//将配置文件中的信息读取到集合中
Properties prop = new Properties();
prop.load(fis);
//获取源文件名称,碎片文件数量
String filename = prop.getProperty("filename");
int count = Integer.parseInt(prop.getProperty("partcount"));
//=======================================================================================================
//【三】获取该目录下所有的碎片文件
File[] partFiles = dir.listFiles(new SuffixFilter(".part"));
if(partFiles.length != (count-1))//原因见上
throw new RuntimeException("碎片个数不对,应该是"+count+"个");
//======================================================================================================
//【四】将碎片文件和流对象关联并存储到集合中
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
for(int x =0; x<partFiles.length;x++){
al.add(new FileInputStream(partFiles[x]));
}
//=====================================================================================================
//【五】将多个流合并成一个序列流
Enumeration<FileInputStream> en = Collections.enumeration(al);
SequenceInputStream sis = new SequenceInputStream(en);
//=======================================================================================================
//【六】读取动作
byte[] buf = new byte[1024];
int len =0;
FileOutputStream fos = new FileOutputStream(new File(dir,filename));
while((len=sis.read(buf))!=-1){
fos.write(buf,0,len);
}
fos.close();
sis.close();
}
}
================================分割线===================================
package demo;
import java.io.File;
import java.io.FilenameFilter;
public class SuffixFilter implements FilenameFilter {
private String suffix;
public SuffixFilter(String suffix) {//由用戶指定过滤文件的后缀名
super();
this.suffix = suffix;
}
@Override
public boolean accept(File dir, String name) {
return name.endsWith(suffix);
}
}