1、实现原理分布写在注释里,基本思路是将源文件分割为若干份,之后再将分割的文件进行合并还原。
2、实现代码如下:
package com.tiger.copy.split.combine;
import java.io.*;
/**
* 文件的分割与合并
* @author tiger
* @Date 2017年7月21日
*/
public class FileSplitAndCombine {
/*
* 测试
*/
public static void main( String[] args )
throws IOException {
String cPath = "E:\\tigerFolder\\J2SE6.0 API(冷冬大雪).chm";
String sPath = "E:\\tigerFolder\\split";
fileSplit(cPath,sPath,9,1024,"chm");
/*================================================================*/
// String srcPath = "E:\\tigerFolder\\split";
// String destPath = "E:\\tigerFolder\\combine.chm";
// fileCombine(srcPath,destPath,9,1024,".chm");
}
/**
* 文件的切割
* @param srcPath 切割源文件路径
* @param destPath 合并文件路径
* @param size 切割块数
* @param speed 切割速度
* @param suffix 切割文件后缀
* @throws IOException 异常处理
*/
public static void fileSplit(String srcPath,String destPath,
int size,int speed,String suffix) throws IOException{
long start = System.currentTimeMillis();
InputStream is = new FileInputStream( srcPath );
//获取文件可读取的字节数,依据这个对文件进行分割
int total = is.available();
//文件分块切割数目 size,余数放到最后一个文件中。
int[] blocks = new int[size];
for (int i = 0; i < size; i++) {
if (i == size - 1) {
blocks[i] = total/size + total%size;
}else {
blocks[i] = total/size;
}
}
//定义创建 size 个输出流的数组.
OutputStream[] outs = new OutputStream[ size ];
for (int i = 0; i < outs.length; i++) {
outs[i] = new FileOutputStream( destPath + i + suffix);
}
int index = 0;
//表示要读取到哪一块,一块一块地读取
int remain = blocks[ index ];
//记录当次需要读取多少个字节
int needRead;
int len = 0;
byte[] buff = new byte[speed];
while( index < size ){
//处理数组越界问题
if( remain > speed ){
needRead = speed;
}else{
needRead = remain;
}
//读取数据
len = is.read( buff, 0, needRead );
if( len != -1 ){
//写出数据、读多少, 写多少
outs[index].write( buff, 0, len );
//强制刷新数据
outs[index].flush();
//读多少减多少
remain = remain - len;
//索引指向下一个文件块
if( remain == 0 ){
index ++;
if( index < size ){
remain = blocks[index];
}
}
}
}
is.close();
long end = System.currentTimeMillis();
System.out.println("执行文件切割耗时: "+(end - start)/1000 + " s");
System.out.println( "程序结束 ..." );
}
/**
* 文件的合并
* @param srcPath 分散文件源文件路径
* @param destPath 合并成功后文件的存放路径
* @param size 源文件数目
* @param speed 合并速度
* @param suffix 合并文件后缀
* @throws IOException 异常处理
*/
public static void fileCombine(String srcPath,String destPath,
int size,int speed,String suffix) throws IOException{
long start = System.currentTimeMillis();
//目标输出流
OutputStream os = new FileOutputStream(destPath,true);//输出的追加的后边
//定义创建 4 个输入流的数组.
InputStream[] is = new InputStream[size];
for (int i = 0; i < size; i++) {
is[i] = new FileInputStream(srcPath + i + suffix);
}
//获取每个文件大小
int[] blocks = new int[size];
for (int i = 0; i < size; i++) {
blocks[i] = is[i].available();
}
int needRead;//一次
int index = 0;//文件号索引
int remain = blocks[index];//记录读取到哪个文件
byte[] buff = new byte[speed];//缓冲,每次读取的大小
int len = 0;//接收数据
while (index < size) {
if( remain > speed ){
needRead = speed;
}else{
needRead = remain; //剩余数 ...
}
//读一次,写一次
len = is[index].read(buff, 0, needRead);//如果字节够,则将byte数组中的数据读完,否则读剩下的。
if (len != -1) {//边读取边输出到本地文件中,读多少,输出多少
os.write(buff, 0, len);//off 需要一个标签来记录,将文件输入到指定文件中。
//读多少,减多少,直到文件大小被减为0 ,则表明文件被读取完毕,接着判断读取下一个文件
remain = remain - len;
}
if( remain == 0 ){//表明文件被读取完毕,接着判断读取下一个文件
//记录文件号
index ++;
if( index < size ){
remain = blocks[index];
}
}
}
os.close();
long end = System.currentTimeMillis();
System.out.println("执行文件合并耗时: "+(end - start)/1000 + " s");
System.out.println( "程序结束 ..." );
}
}