分片工具类
代码语言:javascript复制package com.jinw.utils.file;
import com.jinw.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import java.io.*;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 文件分片、合并工具类
*
* @Author 屋顶上的蜗牛·
* @Date 2021-09-15
*/
@Slf4j
public class FileSplitUtil {
// 定义分块大小
private static final int E_BLOCK_SIZE = 1024 * 1024;
<!--more-->
// 定义解密分块大小 PKCS7Padding 16
private static final int D_BLOCK_SIZE = 1024 * 1024 16;
/**
* 默认切割大小 (单位字节)
* 默认以5M进行切割
*/
private static final int DEFAULT_SIZE = 1024 * 1024 * 5; // 5M
/**
* 子文件下标
*/
private static final int FILE_NAME_EXT = 1000;
/**
* 文件结束标识
*/
private static final int EOF = -1;
/**
* 分片文件组成部分
*/
private static final String SPLIT_FILE_NAME = "-split";
/**
* 匹配分片文件占位符
*/
private static final String PLACEHOLDER = "zzz";
/**
* 切割指定源文件,并输出到指定目录,按默认大小切割
*
* @param srcFile 指定要切割的源文件
* @param outputDir 指定输出目录
* @throws IOException 有异常时抛出,由调用者处理
*/
public static void split(File srcFile, String outputDir) throws IOException {
split(srcFile, outputDir, DEFAULT_SIZE);
}
/**
* 文件分片
*
* @param srcFile 待分片的源文件
* @param outPutDir 分片的输出目录
* @param size 切割大小
* @throws IOException 有异常时抛出,由调用者处理
*/
public static void split(File srcFile, String outPutDir, int size) throws IOException {
BufferedInputStream bis = null;
try {
bis = new BufferedInputStream(new FileInputStream(srcFile));
//拆分成每个为几kb大小的文件
byte[] bytes = new byte[size];
int length;
// 子文件下标
int filenameExt = FILE_NAME_EXT;
while ((length = bis.read(bytes)) > EOF) {
int ext = filenameExt ;
try (BufferedOutputStream bos =
new BufferedOutputStream(new FileOutputStream(outPutDir ext SPLIT_FILE_NAME))) {
bos.write(bytes, 0, length);
}
}
} finally {
IOUtils.closeQuietly(bis);
}
}
/**
* 合并分片文件 默认将合并后的文件放在其分片文件所在目录, 可行性决定
*
* @param sliceDir 所有分片文件所在目录
* @param mergeFileOutputPath 合并输出路径
* @throws IOException 有异常时抛出,由调用者处理
*/
public static void merge(String sliceDir, String mergeFileOutputPath) throws IOException {
List<String> subFileNames = getSplitFileNames(sliceDir);
if (subFileNames.size() < 1) {
throw new ServiceException("目录下没有分片文件...");
}
BufferedOutputStream bos = null;
try {
bos = new BufferedOutputStream(
new FileOutputStream(mergeFileOutputPath));
for (String subFilename : subFileNames) {
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sliceDir subFilename))) {
// 每次读取多大字节的文件
byte[] bytes = new byte[DEFAULT_SIZE];
int length;
while ((length = bis.read(bytes)) > EOF) {
bos.write(bytes, 0, length);
}
bos.flush();
} finally {
File eachSubFile = new File(sliceDir subFilename);
if (eachSubFile.exists() && eachSubFile.delete()) {
log.info("删除分片文件成功...");
}
}
}
} finally {
IOUtils.closeQuietly(bos);
}
}
/**
* 获取目录下的所有分片文件名
*
* @param sliceDir 源目录
* @return 结果
*/
public static List<String> getSplitFileNames(String sliceDir) {
File file = new File(sliceDir);
if (!file.isDirectory()) {
throw new ServiceException("不是一个目录...");
}
String[] list = file.list();
if (list == null || list.length == 0) {
throw new ServiceException("目录下没有任何文件...");
}
// 这里zzz为通用占位符、匹配分片文件
String filename = (PLACEHOLDER SPLIT_FILE_NAME).replace(PLACEHOLDER, "\d ");
return Arrays.stream(list)
.filter(s -> s.matches(filename))
.sorted()
.collect(Collectors.toList());
}
}
分片:
代码语言:javascript复制 FileSplitUtil.split(new File(srcFilePath), splitOutputPath, splitsize);
合并:
代码语言:javascript复制FileSplitUtil.merge(splitDecryptFileOutputPath, mergeFileOutputPath);