实现文件切割器
该方法用于将指定文件 original 切割为体积不超过 size 字节的 N 份后, 依次序 放入到 directory 目录中。
其中:
- 参数 original 表示被拆分的原始文件
- 参数 size 表示拆分后的文件的体积上限
- 参数 directory 表示拆分后的文件的存储目录
代码实现
public int split(final File original, final long size, final File directory) throws IOException {
// 合法校验
if (original != null && !original.isFile()) {
throw new IllegalArgumentException("原始文件不合法");
}
if (directory != null && !directory.isDirectory()) {
throw new IllegalArgumentException("目标目录不合法");
}
if (!directory.getParentFile().exists()) {
directory.getParentFile().mkdirs();
}
int n = 0; // 表示拆分后文件个数的变量
try (FileInputStream fileInputStream = new FileInputStream(original)) {
if (size < Integer.MAX_VALUE - 8) {
byte[] bytes = new byte[(int) size]; // 判断如果传入值大于int最大值,按照int最大值存,要预留一部分空间
int index;
while ((index = fileInputStream.read(bytes)) != -1) { // 按照最大值读文件
File file = new File(directory, System.nanoTime() + ".temp"); // 每部分文件名
try (FileOutputStream fileOutputStream = new FileOutputStream(file)) {
fileOutputStream.write(bytes, 0, index); // 将读的文件写在指定地点
n++;
} catch (IOException e) {
throw new RuntimeException("写文件错误", e);
}
}
} else {
byte[] bytes = new byte[Integer.MAX_VALUE - 8];
while (fileInputStream.available() > 0) {
File outFile = new File(original, System.nanoTime() + ".temp");
try (FileOutputStream fileOutputStream = new FileOutputStream(outFile)) {
long sum = size; // 单个文件剩余大小
while (sum > Integer.MAX_VALUE - 8 && fileInputStream.available() > 0) {
int read = fileInputStream.read(bytes);
fileOutputStream.write(bytes, 0, read);
sum -= read;
}
// 处理没有满足单文件大小, 还有内容没读取
if (fileInputStream.available() != 0) {
int read = fileInputStream.read(bytes);
fileOutputStream.write(bytes, 0, read);
}
n++;
} catch (IOException e) {
throw new RuntimeException("写文件错误", e);
}
}
}
} catch (IOException e) {
throw new RuntimeException("读文件错误", e);
}
return n; // 返回拆分后的文件个数
}
实现文件合并器
该方法用于将指定目录 dir 中的多个文件片段依次序合并到同一个文件 target 中,并返
回合并后的文件体积。
其中:
- 参数 dir 表示文件片段所在的目录
- 对应将大文件拆分后所得到的N个小文件的存放目录
- 参数 target 表示合并后的文件的存放路径名
代码实现
public long join(final File dir, final File target) throws IOException {
// 合法校验
if (dir != null && !dir.isDirectory()) {
throw new IllegalArgumentException("目录不合法");
}
if (target != null && !target.isDirectory()) {
throw new IllegalArgumentException("目标文件不合法");
}
// 保证存储的文件夹存在
if (!target.getParentFile().exists()) {
target.getParentFile().mkdirs();
}
try (FileOutputStream fileOutputStream = new FileOutputStream(target)) {
File[] files = dir.listFiles((d, name) -> name.endsWith(".temp"));
assert files != null;
for (File file : files) {
try (FileInputStream fileInputStream = new FileInputStream(file)) {
byte[] bytes = new byte[8192]; // 缓冲区大小为 8KB
int read;
while ((read = fileInputStream.read(bytes)) != -1) {
fileOutputStream.write(bytes, 0, read);
}
} catch (IOException e) {
throw new IOException("写错误", e);
}
}
} catch (IOException e) {
throw new IOException("写文件错误", e);
}
return target.length(); // 返回合并后的文件大小
}