1 package service; 2 import service.oss.FileUtil; 3 4 import java.io.BufferedInputStream; 5 import java.io.BufferedOutputStream; 6 import java.io.File; 7 import java.io.FileInputStream; 8 import java.io.FileNotFoundException; 9 import java.io.FileOutputStream; 10 import java.io.IOException; 11 import java.io.InputStream; 12 import java.io.RandomAccessFile; 13 import java.io.SequenceInputStream; 14 import java.util.ArrayList; 15 import java.util.List; 16 import java.util.Vector; 17 18 public class SplitFile { 19 //文件的路径 20 private String filePath; 21 //文件名 22 private String fileName; 23 //文件大小 24 private long length; 25 //块数 26 private int size; 27 //每块的大小 28 private long blockSize; 29 //分割后的存放目录 30 private String destBlockPath; 31 //每块的名称 32 private List<String> blockPath; 33 34 public SplitFile(){ 35 blockPath = new ArrayList<String>(); 36 } 37 public SplitFile(String filePath,String destBlockPath){ 38 this(filePath,destBlockPath,1024); 39 } 40 public SplitFile(String filePath,String destBlockPath,long blockSize){ 41 this(); 42 this.filePath= filePath; 43 this.destBlockPath =destBlockPath; 44 this.blockSize=blockSize; 45 init(); 46 } 47 48 /** 49 * 初始化操作 计算 块数、确定文件名 50 */ 51 public void init(){ 52 File src =null; 53 //健壮性 54 if(null==filePath ||!(((src=new File(filePath)).exists()))){ 55 return; 56 } 57 if(src.isDirectory()){ 58 return ; 59 } 60 //文件名 61 this.fileName =src.getName(); 62 63 //计算块数 实际大小 与每块大小 64 this.length = src.length(); 65 //修正 每块大小 66 if(this.blockSize>length){ 67 this.blockSize =length; 68 } 69 //确定块数 70 size= (int)(Math.ceil(length*1.0/this.blockSize)); 71 //确定文件的路径 72 initPathName(); 73 } 74 75 private void initPathName(){ 76 for(int i=0;i<size;i++){ 77 this.blockPath.add(destBlockPath+"/"+this.fileName+".part"+i); 78 } 79 } 80 81 /** 82 * 文件的分割 83 * 0)、第几块 84 * 1、起始位置 85 * 2、实际大小 86 * @param 87 */ 88 public void split(){ 89 long beginPos =0; //起始点 90 long actualBlockSize =blockSize; //实际大小 91 //计算所有块的大小、位置、索引 92 for(int i=0;i<size;i++){ 93 if(i==size-1){ //最后一块 94 actualBlockSize =this.length-beginPos; 95 } 96 spiltDetail(i,beginPos,actualBlockSize); 97 beginPos+=actualBlockSize; //本次的终点,下一次的起点 98 } 99 100 } 101 /** 102 * 文件的分割 输入 输出 103 * 文件拷贝 104 * @param idx 第几块 105 * @param beginPos 起始点 106 * @param actualBlockSize 实际大小 107 */ 108 private void spiltDetail(int idx,long beginPos,long actualBlockSize){ 109 //1、创建源 110 File src = new File(this.filePath); //源文件 111 File dest = new File(this.blockPath.get(idx)); //目标文件 112 //2、选择流 113 RandomAccessFile raf = null; //输入流 114 BufferedOutputStream bos=null; //输出流 115 try { 116 raf=new RandomAccessFile(src,"r"); 117 bos =new BufferedOutputStream(new FileOutputStream(dest)); 118 //读取文件 119 raf.seek(beginPos); 120 //缓冲区 121 byte[] flush = new byte[1024]; 122 //接收长度 123 int len =0; 124 while(-1!=(len=raf.read(flush))){ 125 if(actualBlockSize-len>=0){ //查看是否足够 126 //写出 127 bos.write(flush, 0, len); 128 actualBlockSize-=len; //剩余量 129 }else{ //写出最后一次的剩余量 130 bos.write(flush, 0, (int)actualBlockSize); 131 break; 132 } 133 } 134 } catch (FileNotFoundException e) { 135 e.printStackTrace(); 136 } catch (IOException e) { 137 e.printStackTrace(); 138 }finally{ 139 FileUtil.close(bos,raf); 140 } 141 } 142 /** 143 * 文件的合并 144 */ 145 public void merge(String destPath){ 146 //创建源 147 File dest =new File(destPath); 148 //选择流 149 BufferedOutputStream bos=null; //输出流 150 SequenceInputStream sis =null ;//输入流 151 //创建一个容器 152 Vector<InputStream> vi = new Vector<InputStream>(); 153 try { 154 for (int i = 0; i < this.blockPath.size(); i++) { 155 vi.add(new BufferedInputStream(new FileInputStream(new File(this.blockPath.get(i))))); 156 } 157 bos =new BufferedOutputStream(new FileOutputStream(dest,true)); //追加 158 sis=new SequenceInputStream(vi.elements()); 159 //缓冲区 160 byte[] flush = new byte[1024]; 161 //接收长度 162 int len =0; 163 while(-1!=(len=sis.read(flush))){ 164 bos.write(flush, 0, len); 165 } 166 bos.flush(); 167 FileUtil.close(sis); 168 } catch (Exception e) { 169 }finally{ 170 FileUtil.close(bos); 171 } 172 } 173 /** 174 * @param args 175 */ 176 public static void main(String[] args) { 177 //1024 * 30 表示按照每块30Kb大小分割 178 SplitFile split = new SplitFile("C:\\Users\\Spring\\Desktop\\二期(后台)需求20191209(1).doc","C:/123/",1024); 179 180 System.out.println(split.size); 181 // 182 // split.split(); 183 184 split.merge("C:/123/logFile.doc"); 185 186 } 187 188 }