文件切割合并程序学习笔记
来源:互联网 发布:大势至软件 编辑:程序博客网 时间:2024/05/16 18:12
import java.io.File; import java.io.IOException; import org.junit.Test; public class MainClass { /** * 需求:1>.将一个大文件按大小切割成多个小文件,分割后,删除原文件 2>.将多个被切割后的碎片文件合并成一个文件,合并后删除原来的碎片文件 * 思路分析: * 一、切割文件 * 1.>根据文件路径和文件名获取到该文件 * 2.>切割文件就是将一个文件通过输出流写入到多个文件中,所以要用到一个文件输入流:FileInputStream进行读入内存的操作和 * 多个文件输出流:FileOutputStream类进行写的操作 * 3.>定义缓冲区,进行读取,每读满一个碎片文件进行一次文件流的关闭,关闭后继续写下一个文件 * 4.>碎片文件的名称按照数字命名,第一个文件命名为1.part,第二个命名为2.part * 5.>将文件名称和文件的个数写入到一个properties文件中去方便下次合并操作 * * 二、合并文件 * 1.>根据指定的碎片文件的目录,读取properties配置文件 * 2.>根据properties配置文件,获取碎片文件的数量 * 3.>获取所有碎片文件,并添加到List集合中 * 4.>将List集合利用集合工具类Collections中的方法enumeration将集合中的多个流转化为序列流 * 5.>将序列流中的数据写入到指定的文件中去,写完后删掉所有碎片文件 * * 三、说明 * 本程序支持大文件切割 * 如果正使用的话,还需要测试多线程切割和合并 * 第二个是异常的处理,这个要根据具体需要来处理了 */ //测试:将E:\split下的1.JPG进行切割 @Test public void fileSplit(){ //需要切割的文件 File file = new File("E:\\CrossFire_OBV212_Full.exe"); //切割后的路径 File splitedDir = new File("E:\\split"); SplitFile.fileSplit(file,splitedDir); } //测试:将E:\split下多个碎片文件进行合并,合并后文件存储到指定目录下 @Test public void fileMerge() { //要合并的的碎片文件的目录 File file = new File("E:\\split"); //合并后文件存放的目录 File fileMerged = new File("E:\\merge"); try { MergeFile.fileMerge(file, fileMerged); } catch (IOException e) { e.printStackTrace(); } } } import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.Properties; public class SplitFile { //缓冲区:1M private static final int BUFFERED_SIZE = 1048576; //设定每个文件碎片的大小,根据大小来分割文件,每个文件100M private static final int FILE_SIZE = 104857600; /** * 文件切割 * @param file 要切割的文件 * @param splitDir 切割后的文件路径 * */ public static void fileSplit(File file,File splitedDir) { try { FileInputStream fis = new FileInputStream(file); FileOutputStream fos = null; byte[] buf = new byte[BUFFERED_SIZE]; int len = 0; int count = 0; int filesize = 0; while((len=fis.read(buf))!=-1){ if(filesize>=FILE_SIZE){ //关闭上一个文件的输出流 fos.close(); //置空上一个文件碎片,准备重新创建新的碎片文件 fos = null; //重新计算已经写入新的碎片文件的数据大小 filesize = 0; } if(fos==null) fos = new FileOutputStream(new File(splitedDir,(++count)+".part")); filesize += len; fos.write(buf, 0, len); fos.flush(); } //关闭最后一个写入的碎片文件的流 if(fos != null){ fos.close(); } fis.close(); writeConfig(splitedDir,file,count); clearSourceFile(file); } catch (FileNotFoundException e) { e.printStackTrace(); } catch(IOException ie){ ie.printStackTrace(); } } //删除被切割的文件 private static void clearSourceFile(File file) { file.delete(); } /** * @param splitedDir 文件被切割后的存放路径 * @param file 被切割的文件 * @param count 文件个数 * @throws IOException * */ public static void writeConfig(File splitedDir, File file, int count) throws IOException { //1.创建properties配置文件 File propfile = new File(splitedDir,(count+1)+".properties"); FileOutputStream fos = new FileOutputStream(propfile); //2.用Properties类创建对象,将信息写入到内存中 Properties prop = new Properties(); prop.setProperty("filename", file.getName()); prop.setProperty("count", count+""); //3.将Properties对象store进配置文件 prop.store(fos, "Created By Le.Zhou"); } } import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; 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.List; import java.util.Properties; public class MergeFile { //定义配置文件后缀名 private static final String PROPERTIES_SUFFIX = ".properties"; //定义碎片文件后缀名 private static final String PART_SUFFIX = ".part"; //取缓冲区:1M private static final int BUFFERED_SIZE = 1048576; /** * 根据文件路径读取properties配置文件,并合并指定路径下的文件 * @param filepath 要合并的的碎片文件的目录 * @param fileMerged 碎片文件合并后文件的存放目录 * @throws IOException * */ public static void fileMerge(File filepath, File fileMerged) throws IOException { //检测碎片文件目录是否正确 if(filepath==null || !filepath.isDirectory()){ throw new RuntimeException("提供的碎片文件目录不是一个目录!"); } //检测碎片文件合并后的存放目录是否正确 if(!fileMerged.isDirectory()){ boolean flag = fileMerged.mkdirs(); if(!flag) throw new RuntimeException("创建文件存放路径失败,请提供正确的文件存放路径!"); } //获取properties配置文件 File[] propFiles = getFilesBySuffix(filepath, PROPERTIES_SUFFIX); if(propFiles.length != 1){ throw new RuntimeException(filepath.getPath()+"下,后缀为.properties的文件不存在或数量不唯一"); } Properties prop = getPropObject(propFiles[0]); //从配置文件中读取碎片文件数量 String count = prop.getProperty("count"); String fileName = prop.getProperty("filename"); if(count==null){ throw new RuntimeException("配置文件中的信息有误:count属性对应的值为空"); } //获取被分割的文件碎片 File[] partFiles = getFilesBySuffix(filepath,PART_SUFFIX); List<FileInputStream> flist = new ArrayList<FileInputStream>(); if(Integer.parseInt(count) != partFiles.length) throw new RuntimeException("配置文件中的count属性的值与实际part文件数量不相符"); //将文件碎片添加到一个集合中 for(File f : partFiles){ flist.add(new FileInputStream(f)); } //将文件集合转化为序列流 SequenceInputStream sis = fileList2SeqInputStream(flist); //合并文件 write2Disk(sis, fileMerged, fileName); //关闭序列流 sis.close(); //清除碎片文件 clearDebrisFiles(filepath); } //清除碎片文件 private static void clearDebrisFiles(File filepath) { File[] file = filepath.listFiles(); for(File f : file){ boolean flag = f.delete(); if(!flag) throw new RuntimeException(filepath.getPath()+"下,"+f.getName()+"删除失败!"); } } //将文件集合转化为序列流 private static SequenceInputStream fileList2SeqInputStream( List<FileInputStream> flist) { Enumeration<FileInputStream> enumList = Collections.enumeration(flist); SequenceInputStream sis = new SequenceInputStream(enumList); return sis; } //根据文件后缀获取文件 private static File[] getFilesBySuffix(File filepath, String suffix) { File[] propFiles = filepath.listFiles(new FilterBySuffix(suffix)); return propFiles; } //获取碎片文件数量 private static Properties getPropObject(File propFiles) throws IOException, FileNotFoundException { FileInputStream fis = new FileInputStream(propFiles); //获取properties配置文件中的信息 Properties prop = new Properties(); prop.load(fis); fis.close(); return prop; } //合并文件 private static void write2Disk(SequenceInputStream sis, File fileMerged, String filename) throws IOException { FileOutputStream out = new FileOutputStream(new File(fileMerged, filename)); byte[] buf = new byte[BUFFERED_SIZE]; int len = 0; while((len=sis.read(buf))!=-1){ out.write(buf, 0, len); } out.close(); } } import java.io.File; import java.io.FilenameFilter; /** * 文件后缀名过滤器 * */ public class FilterBySuffix implements FilenameFilter { //后缀名 private String suffix; public FilterBySuffix(String suffix){ this.suffix = suffix; } public boolean accept(File dir, String name) { return name.endsWith(suffix); } }