目标
文件太大不利用进行传输,实现将大文件分割小文件的工具类
开发环境
- 语言: java 1.8
- 操作系统 : windows 7
- 开发工具: idea
代码
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 将大文件分割为小文件
* @author 2689592940@qqcom
* @date 2020/10/10 10:46
*/
public class FileSlice {
private static String FILE_PART_EXT = ".parts";
/**
* 分割文件
*
* @param file 文件
* @param filePieceSize 每个文件大小
*
* @return 文件输出路径
*/
public static String slice(File file, int filePieceSize) {
if (!file.isFile()) {
return null;
}
/**
* 默认64M
*/
if (filePieceSize == -1) {
filePieceSize = 1024 * 1024 * 64;
}
/**
* 计算要分割多少个文件
*/
int howManyParts = calcParts(file.length(), filePieceSize);
/**
* 转换成流
*/
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream(file);
/**
* 获取保存文件路径,不存在则创建
*/
String[] split = file.getName().split("\\.");
String oPath = file.getParent() + "\\" + file.getName() + "_" + System.currentTimeMillis();
if (!(new File(oPath).exists())) {
new File(oPath).mkdirs();
}
/**
* 循环读取内容,分配到不同的区间
*/
int len = -1;
// 计算文件的hash
String ext = split[split.length - 1];
// 定义每次读取的字节数
byte[] buffer = new byte[1024];
for (int i = 1; i <= howManyParts; i++) {
System.out.println("开始第" + i + "次的内容分配");
int total = 0;
// 生成的文件名
String fileName = oPath + "\\" + file.getName() + "_" + i + "." + ext + FILE_PART_EXT;
FileOutputStream fos = new FileOutputStream(fileName);
while ((len = inputStream.read(buffer)) != -1) {
fos.write(buffer, 0, len);
total += len;
if (total == filePieceSize) {
break;
}
}
fos.close();
}
return oPath;
} catch (IOException e) {
System.out.println("文件流读取失败: " + e.getMessage());
return null;
} finally {
if (inputStream != null) {
/**
* 关闭流
*/
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 计算要分割多少个文件
*
* @param length 文件大小
* @param filePieceSize 每个文件的大小
*
* @return int 分为多少块
*/
private static int calcParts(double length, int filePieceSize) {
return (int) Math.ceil(length / (double) filePieceSize);
}
/**
* 将分割好的文件重新链接
*
* @param filePath 被分割好的其中之一文件路径,默认其他块与其在同一目录下
*
* @return 成功返回True,出错则返回False
*/
public static String glue(String filePath) {
File files = new File(filePath);
File[] tempList = files.listFiles((dir, name) -> name.endsWith(FILE_PART_EXT));
if (tempList.length == 0) {
return null;
}
try {
// 输出文件保存路径
String combineFilePath = filePath + "/0/";
File outPutFile = new File(combineFilePath);
if (!outPutFile.exists()) {
outPutFile.mkdirs();
}
// 获取
int lastIndexOf = filePath.lastIndexOf("_");
String combineFileName = combineFilePath + filePath.substring(filePath.lastIndexOf("\\") + 1, lastIndexOf);
FileOutputStream fos = new FileOutputStream(combineFileName);
byte[] buffer = new byte[1024];
for (int i = 0; i < tempList.length; i++) {
File file = tempList[i];
int len = -1;
FileInputStream inputStream = new FileInputStream(file);
while ((len = inputStream.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
inputStream.close();
}
fos.close();
return combineFileName;
} catch (IOException e) {
System.out.println("文件流读取失败: " + e.getMessage());
return null;
}
}
public static void main(String[] args) throws FileNotFoundException {
String filepath = "D:/书籍/test.txt";
// String filepath = "D:/书籍/test.txt";
// System.out.println(FileSlice.slice(new File(filepath), 64 * 1024 * 1024));
System.out.println((new FileInputStream(new File(filepath))));
String path = "D:\\书籍\\test.txt_1602318746849";
System.out.println(FileSlice.glue(path));
}
}
思考
- 分割文件可使用多线程 ? 速度是否会有提升