Java 文件的分割与合并完整代码
package com.maple.file;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays;
import java.util.regex.Pattern;
/**
* 文件的分割与合并 注意要遵循类的设计原则 方法与方法之间耦合度要低 考虑设计模式
*
* @author RhymeChiang
* @date 2017/10/21
*/
public class FileSpliteAndMerge {
private final int BLOCK_SIZE = 5;
private final String DEST_PATH = "c:/user/splitFileDir";
private final String SUFFIX = "split-part-";
private final String FILE_NAME_MASK = "_";
private String fileName;
/**
* 源文件
*/
private String srcPath;
/**
* 分割文件的保存目录
*/
private String destPath;
/**
* 文件分割块的大小
*/
private long blockSize;
/**
* 文件的分割块数
*/
private int blocksNumber;
/**
* 无参构造方法 初始化分割块的大小 初始化分割文件的默认保存位置
*/
public FileSpliteAndMerge() {
super();
this.blockSize = BLOCK_SIZE;
this.destPath = DEST_PATH;
}
/**
* 分割文件构造方法
*
* @param blockSize
* 文件分割块的大小
* @param srcPath
* 文件分割源文件
* @param destPath
* 分割文件保存位置
*/
public FileSpliteAndMerge(long blockSize, String srcPath, String destPath) {
super();
this.blockSize = blockSize;
this.srcPath = srcPath;
this.destPath = destPath;
}
/**
* 文件分割总方法重载方法
*/
public void splitFile() {
if (null == srcPath || srcPath.equals("")) {
System.out.println("请使用setSrcPath(String)设置源文件路径");
}
splitFile(srcPath, blockSize, destPath);
}
/**
* 文件分割总方法
*
* @param srcPath
* 源文件路径
* @param blockSize
* 分割块的大小
*/
public void splitFile(String srcPath, long blockSize, String destPath) {
File src = new File(srcPath);
// 文件位置保存不合法则直接返回
if (!checkSaveDir(destPath)) {
return;
}
// 文件不合法直接退出
if (!checkFile(src)) {
System.out.println("文件不存在或不合法,请确保文件路径正确且该文件不是目录");
return;
}
try {
splitFileDetail(src, blockSize, destPath);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 合并splitFilesDir目录下的分割文件
*
* @param splitFilesDir
* @param destPath
*/
public void mergeSplitFiles(String splitFilesDir, String destPath) {
File splitDir = new File(splitFilesDir);
if(!checkSplitFileDir(splitDir)) {
return;
}
try {
mergeSplitFilesDetails(splitDir, destPath);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 合并分割文件具体操作
*
* @param splitDir
* 分割文件所在目录
* @param destPath
* 合并文件保存位置
* @throws IOException
*/
private void mergeSplitFilesDetails(File splitDir, String destPath) throws IOException {
File[] listFiles = splitDir.listFiles();
fileName = getSplitFileName(listFiles[0]);
int filesNum = listFiles.length;
//合并文件目录保存位置不合法
if(!checkMergeDestPath(fileName,destPath)) {
return;
}
/**
* 写到指定文件并追加
*/
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(destPath,fileName)));
for (int i = 1; i <= filesNum; i++) {
for(File f:listFiles) {
if(f.getName().contains(i+"")) {
bos.write(readFile(f));
bos.flush();
break;
}
}
}
bos.flush();
closeAll(bos);
}
/**
* 检车合并文件目录保存的合法性
* @param mergeFileName
* @param destPath
* @return
*/
public boolean checkMergeDestPath(String mergeFileName,String destPath) {
File dest = new File(destPath);
if(!dest.exists()) {
System.out.println("合并文件保存地址不存在");
return false;
}
if(!dest.isDirectory()) {
System.out.println("合并文件保存地址不是一个目录");
return false;
}
for(File f:dest.listFiles()) {
if(f.getName().equals(mergeFileName)) {
System.out.println("合并保存地址中存在和保存文件同名的文件");
return false;
}
}
return true;
}
/**
* 将文件中内容读入字节数组中
* @param f
* @return
* @throws IOException
*/
private byte[] readFile(File f) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len = 0;
byte [] buffer = new byte[1024];
while(-1!=(len=bis.read(buffer))) {
baos.write(buffer,0,(int)f.length());
}
byte[] byteArray = baos.toByteArray();
closeAll(baos,bis);
return byteArray;
}
/**
* 获取分割文件原名
*
* @param f
* @return
*/
public String getSplitFileName(File f) {
String name = f.getName();
return name.substring(name.indexOf(FILE_NAME_MASK)+1);
}
/**
* 检查分割文件目录以及其中的目录是否合法
*
* @param splitDir
* @return
*/
private boolean checkSplitFileDir(File splitDir) {
if (!splitDir.exists()) {
System.out.println("分割文件指定目录不存在");
return false;
}
if (!splitDir.isDirectory()) {
System.out.println("分割文件指定目录不是一个目录");
return false;
}
String fileName = getSplitFileName(splitDir.listFiles()[0]);
String reg = SUFFIX + "\\d*"+"_"+fileName;
for (File f : splitDir.listFiles()) {
if (!f.getName().matches(reg)) {
System.out.println("目录中包含非法分割文件");
return false;
}
}
return true;
}
/**
* 检查是否为一个合法的文件
*
* @param src
* 源文件地址
* @return
*/
private boolean checkFile(File src) {
// 如果文件不存在或文件为目录则返回false
if (!src.exists() || src.isDirectory()) {
return false;
}
// 文件合法返回true
return true;
}
/**
* 文件分割具体操作
*
* @param src
* 源文件
* @param blockSize
* 分割快的大小,单位为字节
* @throws IOException
*/
private void splitFileDetail(File src, long blockSize, String destPath) throws IOException {
// 如果分割块的大小大于总文件大小,则将其调整为文件的总大小
if (blockSize > src.length()) {
blockSize = src.length();
}
// 总的分割块的块数
blocksNumber = (int) Math.ceil(src.length() * 1.0 / blockSize);
/**
* 进行文件的分割,使用以下的方法读取定长的文件字符 int read(byte[] b, int off, int len)
* 创建RandomAccessFile对象并设置模式为r只读
**/
RandomAccessFile rf = new RandomAccessFile(src, "r");
byte buffer[] = new byte[(int) blockSize];
int len = -1;
int count = 1;
while (-1 != rf.read(buffer)) {
saveByteToFile(src, count, buffer, destPath);
count++;
}
closeAll(rf);
}
/**
* 将分割文件进行保存
*
* @param data
* @param destPath
* @throws FileNotFoundException
*/
private void saveByteToFile(File src, int count, byte[] data, String destPath)
throws FileNotFoundException, IOException {
File dest = new File(destPath);
FileOutputStream fos = null;
BufferedOutputStream bos = null;
dest = new File(dest, SUFFIX + count + FILE_NAME_MASK + src.getName());
fos = new FileOutputStream(dest);
bos = new BufferedOutputStream(fos);
// 将分割数据写入到文件中
bos.write(data, 0, data.length);
bos.flush();
// 关闭流
closeAll(bos, fos);
}
/**
* 确保分割文件保存目录的合法性 即确保文件保存位置存在且为一个空目录
*
* @param dest
* @return
*/
private boolean checkSaveDir(String destPath) {
File dest = new File(destPath);
// 确保目标目录存在
if (!dest.exists() || !dest.isDirectory()) {
System.out.println("分割文件保存位置不存在或文件保存位置不是一个目录");
return false;
}
// 确保保存目录为空目录,避免目录中有文件和分割文件发生同名冲突
if (dest.listFiles().length != 0) {
System.out.println("分割文件保存目录不是一个空目录,请选择一个空目录作为分割文件的保存位置");
return false;
}
return true;
}
/**
* 获取文件的后缀名
*
* @param src
* @return
*/
public String getFileSuffix(File src) {
String fileName = src.getName();
int lastEnd = fileName.indexOf(".");
return fileName.substring(lastEnd);
}
/**
* 获取文件名
*
* @param src
* @return
*/
public String getFileName(File src) {
String fileName = src.getName();
int lastEnd = fileName.indexOf(".");
return fileName.substring(0, lastEnd);
}
/**
* IO流关闭工具类
*
* @param io
*/
private <T extends Closeable> void closeAll(T... io) {
for (T o : io) {
if (null != o) {
try {
o.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public String getSrcPath() {
return srcPath;
}
public void setSrcPath(String srcPath) {
this.srcPath = srcPath;
}
public long getBlockSize() {
return blockSize;
}
public void setBlockSize(long blockSize) {
this.blockSize = blockSize;
}
public String getDestPath() {
return destPath;
}
public void setDestPath(String destPath) {
this.destPath = destPath;
}
public static void main(String[] args) {
FileSpliteAndMerge f = new FileSpliteAndMerge(5, "E://print.txt", "E://Test");
f.splitFile();
f.mergeSplitFiles("E://Test", "E://Test2");
}
}