一、功能代码
import java.io.*;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* 1.把大文件按照指定大小分割成多个小文件
* 2.把多个小文件分割为大文件
* 测试用例@com.xm.FileSplitAndCombineTest
*/
public class FileSplitAndCombine {
private static int COUNT= 29; // 拆成的每个的体积MB数
/**
* 把大文件拆分为多个小文件
*
* @param sourcePath 需要被拆分的文件路径
* @param desPath 拆分后的文件应该存放的文件路径
* @param newName 每一个小文件名
*/
public static void splitFile(String sourcePath, String desPath, String newName) {
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(sourcePath)))) {
for (int i = 0; ; i++) {
String filePath = desPath + File.separatorChar +newName+"_" +i;
if (singleSplitFile(bis, filePath, COUNT)) break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* @param bis 输入流
* @param filePath 新文件存储的文件夹路径
* @param partitionSize 每个文件的大小 单位MB
* @throws IOException
*/
private static boolean singleSplitFile(BufferedInputStream bis, String filePath,int partitionSize) throws IOException {
int length = partitionSize * 1024 * 1024;
byte[] buffer = new byte[1024];
int tempLength;
System.out.println(nowTime() + "----->>>> begin split " + filePath);
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(filePath)))) {
while ((tempLength = bis.read(buffer)) != -1) {
bos.write(buffer, 0, tempLength);
if ((length = length - tempLength) <= 0) break;
}
}
System.out.println(nowTime() + "<<<<----- yet finish split" + filePath);
return tempLength < 0;
}
/**
* 把指定文件夹内的文件合并为一个文件
*
* @param sourcePath 需要被合并的文件所在的文件中路径
* @param desPath 合并后的文件存放位置
*/
public static void combineFile(String sourcePath, String desPath) {
List<String> sortedFileNames = sortFilesName(sourcePath);
if (sortedFileNames == null) {
System.out.println(sourcePath+"路径下不存在文件夹");
return;
}
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(desPath)))) {
for (String sortedFileName : sortedFileNames) {
copyFile(bos, sourcePath + File.separatorChar + sortedFileName);
}
System.out.println("all finish...");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 把目标文件合并到输出流中
*
* @param bos 缓冲输出流
* @param des 目标文件路径
* @throws IOException
*/
private static void copyFile(BufferedOutputStream bos, String des) throws IOException {
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(des)))) {
System.out.println(nowTime()+ "------>>>>"+des + "开始合并");
byte[] bytes = new byte[1024];
int length;
while ((length = bis.read(bytes)) != -1) {
bos.write(bytes, 0, length);
}
System.out.println(nowTime()+ "<<<<------"+des + "合并完成");
}
}
/**
* 对指定文件夹内的文件名进行排序 (增序)
*
* @param fileDir
* @return
*/
private static List<String> sortFilesName(String fileDir) {
File file = new File(fileDir);
File[] files = file.listFiles();
if (null == files || files.length == 0) {
return null;
}
Pattern compile = Pattern.compile("^.+_\\d+[csdnCommentCode]");
return Arrays.stream(files).map(File::getName)
.sorted((fileName1,fileName2)->{
String[] split1 = fileName1.split("_");
String[] split2 = fileName2.split("_");
return Integer.parseInt(split1[split1.length - 1]) - Integer.parseInt(split2[split2.length - 1]);
}).collect(Collectors.toList());
}
private static String nowTime(){
return new Date().toString();
}
}
二.测试用例
public class FileSplitAndCombineTest {
public static void main(String[] args) {
//文件分割
//splitTest();
//文件合并
combineTest();
}
private static void splitTest() {
String sourcePath = "D:\\test\\文件.rar";
String desPath = "D:\\test";
String newName = "split";
FileSplitAndCombine.splitFile(sourcePath, desPath, newName);
}
private static void combineTest() {
String desPath = "D:\\test\\文件.rar";
String sourcePath = "D:\\test";
FileSplitAndCombine.combineFile(sourcePath, desPath);
}
}