需求: 某文件太大, 需要拆分保存, 问如何快速拆分? 拆分后如何完整合并?
使用的java类: RandomAccessFile + BufferedInputStream+ BufferedOutputStream
=========================================================
拆分思路:
RandomAccessFile rf = new RandomAccessFile(srcFile,"rw");//把文件加载到内存
rf.read( byte数组a ); //rf释放文件的一部分:到数组中
BufferedOutputStream out = new BufferedOutputStream( 文件1,2,3,4.... );
out.write(byte数组a) //把数组中的东西 写入文件1,2,3,4...
合并思路:
file.listFiles():查找出文件数组, Arrays.sort(数组,比较器)-->使其按照后缀名排序【文件1,2,3,4.....】
依次把文件内容写入到:同一个文件
=========================================================
/**
* a.tar.gz--->均分为n份, 例如如每份大小50m, ======>合并该目录下的_1,_2..._n文件为a.tar.gz
*
* @author wang
*
*/
//拆分:大文件--->指定目录
static void split(String srcFile1,String todir1,int fileSize) throws Exception {
File srcFile=new File(srcFile1);
File todir=new File(todir1);
//判断目标文件夹:是否存在
if(!todir.exists()) {
todir.mkdirs();
}
//计算: 拆多少份? 拆分后的文件名, partSize(MB)
long len=srcFile.length();
long size=fileSize*(1024*1024);
//int fileCount=(int)(len%size==0?len/size:len/size+1);
int fileCount=0;
boolean isOdd=false;//是否:不能整除
if(len%size==0){
fileCount=(int)(len/size);
}else {
fileCount=(int)(len/size)+1;
isOdd=true;//不能整除
}
//使用:RandomAccessFile--->读全部文件---->写部分文件到: Part-file
RandomAccessFile rf = new RandomAccessFile(srcFile,"rw");
//创建: n个文件
File[] fs=new File[fileCount];
for(int i=1;i<=fileCount;i++) {
fs[i-1]=new File(todir,srcFile.getName()+"_"+i);
//打印日志---------
System.out.println("after splite , file name -->"+fs[i-1].getName()
+",\t file size: "+fs[i-1].length());
//byte[]---数组大小==内容大小, 最后一个文件特殊: 大小待定?
BufferedOutputStream out = new BufferedOutputStream( new FileOutputStream(fs[i-1]) );
//容器: rf放内容到数组中
byte[] bs;
if(i==fileCount && isOdd==true) {
bs=new byte[(int) (len-(fileCount-1)*size)];
}else {
bs=new byte[(int) size];
}
rf.read(bs);
//输出流: 从数组中拿东西
out.write(bs);
}
System.out.println("split ok....\n");
}
}
static void merge(String fromDir, String toDir) throws Exception {
// 判断目标文件夹:是否存在
File srcDir = new File(fromDir);
File todir = new File(toDir);
if (!todir.exists()) {
todir.mkdirs();
}
// 遍历: 该目录的所有子文件, 合并为一个文件
File[] fs = srcDir.listFiles();
// -------------------查找目标文件名=> 原文件名 start-------------------
String name = null;
for (int i = 0; i < fs.length; i++) {
// 获取文件名a.tar.gz_1
String thisname = fs[i].getName();
if (fs[i].isFile() && thisname.lastIndexOf("_") != -1 && thisname.endsWith("" + 1)) {
name = fs[i].getName().replaceAll("_[a-zA-Z0-9]+", "");
break;
}
} // -------------------查找目标文件名=>原文件名 end-------------------
Arrays.sort(fs, new Comparator() {// 使得数组有序: 按后缀_1,_2, _3...排序
@Override
public int compare(File o1, File o2) {
// 文件排序: 1,2,3,4
int index1 = o1.getName().indexOf("_");
int num1 = Integer.parseInt(o1.getName().substring(index1 + 1));
int index2 = o2.getName().indexOf("_");
int num2 = Integer.parseInt(o2.getName().substring(index2 + 1));
return num1 - num2;
}
});
// -------------顺序合并:多个文件 start -----------------------
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(new File(todir, name)));
for (int i = 0; i < fs.length; i++) {
// 文件拷贝: 合并为一个文件
String thisname = fs[i].getName();
if (fs[i].isFile() && thisname.endsWith("" + (i + 1))) {// 再次检验: 文件后缀 是否以 i+1结尾
System.out.println("文件顺序: " + (i + 1) + ", file name====>" + thisname);
BufferedInputStream in = new BufferedInputStream(new FileInputStream(fs[i]));
int len = 0;
byte[] bs = new byte[1024];
while ((len = in.read(bs)) != -1) {
out.write(bs, 0, len);
out.flush();
}
// 关闭资源
in.close();
} // if
} // for
// -------------顺序合并:多个文件 end -----------------------
out.close();
System.out.println("merge ok....");
}
//测试:验证结果
public static void main(String[] args) throws Exception {
split("/home/wang/a.tar.gz","/home/wang/test",50);
merge("/home/wang/test", "/home/wang/test2");
}