Skip to content

Commit 41e7f13

Browse files
committed
Add FileSplitUtil
1 parent 6da8f6e commit 41e7f13

1 file changed

Lines changed: 116 additions & 0 deletions

File tree

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package com.blankj.utilcode.util;
2+
3+
import android.os.Build;
4+
import android.support.annotation.RequiresApi;
5+
6+
import java.io.File;
7+
import java.io.IOException;
8+
import java.io.RandomAccessFile;
9+
import java.nio.channels.FileChannel;
10+
import java.util.ArrayList;
11+
import java.util.List;
12+
import java.util.UUID;
13+
14+
/**
15+
* <pre>
16+
* author: UFreedom
17+
* blog : http://ufreedom.me
18+
* time : 2018/09/29
19+
* desc : Util for file split
20+
* </pre>
21+
*/
22+
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
23+
public class FileSplitUtil {
24+
25+
26+
/**
27+
* Split a file into multiples files
28+
*
29+
* @param destCacheDir The dir to be cached for split files
30+
* @param srcFile The file need to be split
31+
* @param expireSplitCount How many files are expected to be cut.The value should at least 2.
32+
* Sometimes a file may not be cut into a specific number.For example, Expire cut into 3,
33+
* but the current file can not be completely cut after cutting 3, there may be a little left,
34+
* and it will eventually be cut into 4
35+
* @return 切片后的结果
36+
*/
37+
public static List<File> splitFile(File destCacheDir, final int expireSplitCount, final File srcFile) throws IOException {
38+
checkDestDir(destCacheDir);
39+
checkSourceFile(srcFile);
40+
if (expireSplitCount < 2) {
41+
throw new IllegalArgumentException("The split count must at least 2");
42+
}
43+
44+
final long sourceSize = srcFile.length();
45+
long bytesPerSplit = sourceSize / expireSplitCount;
46+
return splitFileInner(destCacheDir, srcFile, sourceSize, bytesPerSplit, expireSplitCount);
47+
}
48+
49+
50+
/**
51+
* Split a file into multiples files
52+
*
53+
* @param destCacheDir The dir to be cached for split files
54+
* @param srcFile The file need to be split
55+
* @param sliceSize How big is each slice are expected to be cut. Unit(MB)
56+
*/
57+
public static List<File> splitFile(File destCacheDir, final File srcFile, final int sliceSize) throws IOException {
58+
59+
checkDestDir(destCacheDir);
60+
checkSourceFile(srcFile);
61+
62+
if (sliceSize <= 0) {
63+
throw new IllegalArgumentException("The slice size must be more than zero");
64+
}
65+
66+
final long sourceSize = srcFile.length();
67+
final long bytesPerSplit = 1024L * 1024L * sliceSize;
68+
final long numSplits = sourceSize / bytesPerSplit;
69+
70+
return splitFileInner(destCacheDir, srcFile, sourceSize, bytesPerSplit, numSplits);
71+
}
72+
73+
private static List<File> splitFileInner(File destDir, File srcFile, long sourceSize, long bytesPerSplit, long numSplits) throws IOException {
74+
List<File> partFiles = new ArrayList<>();
75+
final long remainingBytes = sourceSize % bytesPerSplit;
76+
int position = 0;
77+
RandomAccessFile sourceFile = new RandomAccessFile(srcFile, "r");
78+
FileChannel sourceChannel = sourceFile.getChannel();
79+
for (; position < numSplits; position++) {
80+
writePartToFile(destDir, bytesPerSplit, position * bytesPerSplit, sourceChannel, partFiles);
81+
}
82+
83+
if (remainingBytes > 0) {
84+
writePartToFile(destDir, remainingBytes, position * bytesPerSplit, sourceChannel, partFiles);
85+
}
86+
return partFiles;
87+
}
88+
89+
private static void writePartToFile(File destDirFile, long byteSize, long position, FileChannel sourceChannel, List<File> partFiles) throws IOException {
90+
String tempDir = destDirFile.getAbsolutePath().concat("/");
91+
File file = new File(tempDir + UUID.randomUUID() + "_" + position + "" + ".splitPart");
92+
RandomAccessFile toFile = new RandomAccessFile(file, "rw");
93+
FileChannel toChannel = toFile.getChannel();
94+
sourceChannel.position(position);
95+
toChannel.transferFrom(sourceChannel, 0, byteSize);
96+
partFiles.add(file);
97+
}
98+
99+
private static void checkSourceFile(File srcFileName) {
100+
if (srcFileName == null || !srcFileName.exists()) {
101+
throw new NullPointerException("The source file should be non-empty or exist");
102+
}
103+
}
104+
105+
private static void checkDestDir(File cacheDir) {
106+
if (cacheDir == null || !cacheDir.exists()) {
107+
throw new NullPointerException("The cache directory should exist");
108+
}
109+
110+
if (!cacheDir.isDirectory()) {
111+
throw new IllegalArgumentException("The cache directory should not be a file");
112+
}
113+
}
114+
115+
116+
}

0 commit comments

Comments
 (0)