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 }