Java实现文件切片和合并

Java实现文件切片和合并

摘要

日常工作中,会有对文件传输的需求,那么文件传输中,如果是小文件,可以一次性的传输过去,那么如果是比较大的文件呢,比如:十几MB的呢
如果一次性传输肯定很慢,并且还有带宽占用大、文件传输慢的问题,这里面我们就可以通过对文件切片后,分段传输,下面是具体的代码实现

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/**
* Copyright 2020. javaymw.com Studio All Right Reserved
* <p>
* Create on 04-13 11:08
* Created by zhaoxinguo
* Version 2.0.0
*/
package org.javaymw.base.utils;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

/**
* @description: Java实现文件切片和合并
* @author zhaoxinguo
* @date 2020/4/13 11:08
*/
public class FileSplitUtil {

/**
* 文件拆分
* @param file
* @param count
*/
public static void getSplitFile(String file, int count) {
//预分配文件所占用的磁盘空间,在磁盘创建一个指定大小的文件,“r”表示只读,“rw”支持随机读写
try {
RandomAccessFile raf = new RandomAccessFile(new File(file), "r");
//计算文件大小
long length = raf.length();
System.out.println(length);
//计算文件切片后每一份文件的大小
long maxSize = length / count;
System.out.println(maxSize);

//定义初始文件的偏移量(读取进度)
long offset = 0L;
//开始切割文件
//count-1最后一份文件不处理
for(int i = 0; i < count - 1; i++){
//标记初始化
long fbegin = offset;
//分割第几份文件
long fend = (i+1) * maxSize;
//写入文件
offset = getWrite(file, i, fbegin, fend);
}

//剩余部分文件写入到最后一份(如果不能平平均分配的时候)
if (length - offset > 0) {
//写入文件
getWrite(file, count-1, offset, length);
}
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* 指定文件每一份的边界,写入不同文件中
* @param file 源文件
* @param index 源文件的顺序标识
* @param begin 开始指针的位置
* @param end 结束指针的位置
* @return long
*/
public static long getWrite(String file, int index, long begin, long end) {
long endPointer = 0L;
try {
//申明文件切割后的文件磁盘
RandomAccessFile in = new RandomAccessFile(new File(file), "r");
//定义一个可读,可写的文件并且后缀名为.tmp的二进制文件
RandomAccessFile out = new RandomAccessFile(new File(file + "_" + index + ".tmp"), "rw");

//申明具体每一文件的字节数组
byte[] b = new byte[1024];
int n = 0;
//从指定位置读取文件字节流
in.seek(begin);
//判断文件流读取的边界
while (in.getFilePointer() <= end && (n = in.read(b)) != -1) {
//从指定每一份文件的范围,写入不同的文件
out.write(b, 0, n);
}

//定义当前读取文件的指针
endPointer = in.getFilePointer();

//关闭输入流
in.close();
//关闭输出流
out.close();
} catch (Exception e) {
e.printStackTrace();
}

return endPointer;
}

/**
* 文件合并
* @param file 指定合并文件
* @param tempFile 分割前的文件名
* @param tempCount 文件个数
*/
public static void merge(String file, String tempFile, int tempCount) {
RandomAccessFile raf = null;
try {
//申明随机读取文件RandomAccessFile
raf = new RandomAccessFile(new File(file), "rw");
//开始合并文件,对应切片的二进制文件
for (int i = 0; i < tempCount; i++) {
//读取切片文件
RandomAccessFile reader = new RandomAccessFile(new File(tempFile + "_" + i + ".tmp"), "r");
byte[] b = new byte[1024];
int n = 0;
while ((n = reader.read(b)) != -1) {
//一边读,一边写
raf.write(b, 0, n);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

public static void main(String[] args) {
/**
* 第一步
*/
String file = "D:\\BaiduNetdiskDownload\\Beginning Spring Boot 2.pdf";
int count = 5;
//1.根据现有的文件编写文件编写文件切片工具类
//2.写入到二进制临时文件
getSplitFile(file, count);
/**
* 第二步
*/
//3.根据实际的需求合并指定数量的文件
String mergeFile = "D:\\BaiduNetdiskDownload\\Beginning Spring Boot 2_temp.pdf";
merge(mergeFile, file, count);
}
}

文件拆分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
* 文件拆分
* @param file
* @param count
*/
public static void getSplitFile(String file, int count) {
//预分配文件所占用的磁盘空间,在磁盘创建一个指定大小的文件,“r”表示只读,“rw”支持随机读写
try {
RandomAccessFile raf = new RandomAccessFile(new File(file), "r");
//计算文件大小
long length = raf.length();
System.out.println(length);
//计算文件切片后每一份文件的大小
long maxSize = length / count;
System.out.println(maxSize);

//定义初始文件的偏移量(读取进度)
long offset = 0L;
//开始切割文件
//count-1最后一份文件不处理
for(int i = 0; i < count - 1; i++){
//标记初始化
long fbegin = offset;
//分割第几份文件
long fend = (i+1) * maxSize;
//写入文件
offset = getWrite(file, i, fbegin, fend);
}

//剩余部分文件写入到最后一份(如果不能平平均分配的时候)
if (length - offset > 0) {
//写入文件
getWrite(file, count-1, offset, length);
}
} catch (Exception e) {
e.printStackTrace();
}
}

指定文件每一份的边界,写入不同文件中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**
* 指定文件每一份的边界,写入不同文件中
* @param file 源文件
* @param index 源文件的顺序标识
* @param begin 开始指针的位置
* @param end 结束指针的位置
* @return long
*/
public static long getWrite(String file, int index, long begin, long end) {
long endPointer = 0L;
try {
//申明文件切割后的文件磁盘
RandomAccessFile in = new RandomAccessFile(new File(file), "r");
//定义一个可读,可写的文件并且后缀名为.tmp的二进制文件
RandomAccessFile out = new RandomAccessFile(new File(file + "_" + index + ".tmp"), "rw");

//申明具体每一文件的字节数组
byte[] b = new byte[1024];
int n = 0;
//从指定位置读取文件字节流
in.seek(begin);
//判断文件流读取的边界
while (in.getFilePointer() <= end && (n = in.read(b)) != -1) {
//从指定每一份文件的范围,写入不同的文件
out.write(b, 0, n);
}

//定义当前读取文件的指针
endPointer = in.getFilePointer();

//关闭输入流
in.close();
//关闭输出流
out.close();
} catch (Exception e) {
e.printStackTrace();
}

return endPointer;
}

文件合并

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
* 文件合并
* @param file 指定合并文件
* @param tempFile 分割前的文件名
* @param tempCount 文件个数
*/
public static void merge(String file, String tempFile, int tempCount) {
RandomAccessFile raf = null;
try {
//申明随机读取文件RandomAccessFile
raf = new RandomAccessFile(new File(file), "rw");
//开始合并文件,对应切片的二进制文件
for (int i = 0; i < tempCount; i++) {
//读取切片文件
RandomAccessFile reader = new RandomAccessFile(new File(tempFile + "_" + i + ".tmp"), "r");
byte[] b = new byte[1024];
int n = 0;
while ((n = reader.read(b)) != -1) {
//一边读,一边写
raf.write(b, 0, n);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

代码测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args) {
/**
* 第一步
*/
String file = "D:\\BaiduNetdiskDownload\\Beginning Spring Boot 2.pdf";
int count = 5;
//1.根据现有的文件编写文件编写文件切片工具类
//2.写入到二进制临时文件
getSplitFile(file, count);
/**
* 第二步
*/
//3.根据实际的需求合并指定数量的文件
String mergeFile = "D:\\BaiduNetdiskDownload\\Beginning Spring Boot 2_temp.pdf";
merge(mergeFile, file, count);
}

运行结果

TIM截图20200413113100.png

MiCai wechat
扫一扫,关注微信订阅号
坚持原创技术分享,您的支持将鼓励我继续创作!