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( "程式結束 ..." );
}
}