文件的拆分与合并
package io;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
public class SplitFile {
// 文件路径
private String filePath;
// 合成文件路径
private String destPath;
// 源文件名
private String fileName;
// 源文件的大小
private long length;
// 块数 - 划分的文件数
private int size;
// 每块的大小 - 每个文件的大小
private long blockSize;
// 每块的名称 - 每个文件的文件名
private List<String> blockPath;
private SplitFile() {
blockPath = new ArrayList<String>();
}
public SplitFile(String filePath, String destPath) {
this(filePath, destPath, 1024);
}
public SplitFile(String filePath, String destPath, long blockSize) {
this();
this.blockSize = blockSize;
this.filePath = filePath;
this.destPath = destPath;
init();
}
// 初始化操作,计算划分的文件数
public void init() {
File src = null;
// 如果文件路径为空,或者文件不存在直接返回
if (null == filePath || !((src = new File(filePath)).exists())) {
return;
}
if (src.isDirectory()) {
return;
}
this.fileName = src.getName();
// 计算文件数, 文件实际大小,每个文件大小
this.length = src.length();
// 如果实际文件大小 小于要划分的每件文件大小,那么将修改文件大小
if (this.blockSize > length) {
this.blockSize = length;
}
// 确定文件数
size = (int) Math.ceil((length * 1.0) / this.blockSize);
initPathName();
}
// 确定文件名
private void initPathName() {
for (int i = 0; i < size; i++) {
this.blockPath.add(this.destPath + "/" + this.fileName + ".part" + i);
}
}
/**
* 文件的分割 0) 第几个文件 1) 起始位置 2) 分割大小
*
* @param destPath
* - 分割后文件的存放目录
*/
public void split() {
long startPos = 0;
long actualBlockSize = blockSize;
for (int i = 0; i < size; i++) {
if (i == size - 1) {
actualBlockSize = this.length - startPos;
}
splitDetail(i, startPos, actualBlockSize);
startPos += actualBlockSize;
}
}
private void splitDetail(int i, long startPos, long actualBlockSize) {
// 创建源
File src = new File(filePath);
File dest = new File(this.blockPath.get(i));
// 选择流
RandomAccessFile randomAccessFile = null; // 输入流
BufferedOutputStream bos = null; // 输出流
try {
randomAccessFile = new RandomAccessFile(src, "r");
randomAccessFile.seek(startPos);
bos = new BufferedOutputStream(new FileOutputStream(dest, true));
byte[] flush = new byte[1024];
int len = 0;
while (-1 != (len = randomAccessFile.read(flush))) {
// 当文件可存储大小 >
// 读取的长度,可以按照读取的len长度直接输出,当可存储大小<读取长度,证明这是这个文件最后一次读取,按照实际可存储大小输出后,退出循环
if (actualBlockSize - len >= 0) {
bos.write(flush, 0, len);
actualBlockSize -= len;
} else {
bos.write(flush, 0, (int) actualBlockSize);
break;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
randomAccessFile.close();
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void merge() {
// 创建多个文件的数据源和输入流,一个目的源和输出流
SequenceInputStream bis = null;
BufferedOutputStream bos = null;
try {
bos = new BufferedOutputStream(new FileOutputStream(new File(this.destPath, this.fileName), true));
Vector vector = new Vector<InputStream>();
for (int i = 0; i < this.size; i++) {
File subFile = new File(this.blockPath.get(i));
vector.addElement(new FileInputStream(subFile));
}
bis = new SequenceInputStream(vector.elements());
byte[] flush = new byte[1024];
int len = 0;
while (-1 != (len = bis.read(flush))) {
bos.write(flush, 0, len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bis.close();
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
SplitFile file2 = new SplitFile("C:/TestProject/msg.txt",
"C:/TestProject/filesplite", 1024);
System.out.println(file2.size);
file2.split();
file2.merge();
}
}