package fileSplitAndBination;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
/**
* 文件的分割
* @author 風瀟瀟
*
*/
public class FileSplit {
//文件路徑
private String srcPath;
//文件對象
private File src;
//源文件大小
private long fileSize;
//源文件名
private String name;
//分割塊數
private int blocks;
//每塊大小
private long blockSize;
//分割後存儲路徑
public FileSplit(String srcPath){
this(srcPath,10);//默認分割爲十塊
}
/**
* 默認爲讀取源文件目錄,和分割塊數
* @param srcPath
* @param blocks
*/
public FileSplit(String srcPath,int blocks){
this.srcPath = srcPath;
this.blocks=blocks;
initial();
}
/**
* 讀取文件名,文件大小,計算分割後每塊大小
*/
public void initial(){
this.src=new File(srcPath);
if(!src.isFile()){
System.out.println("傳入文件夾只能分割文件,或文件不存在");
return;
}
this.fileSize=src.length();//文件大小
this.name=src.getName();//文件名
this.blockSize = fileSize/blocks;//分割塊大小
}
/**
* 指定輸出目錄
* @param destPath
* @throws IOException
*/
public void split(String destPath) throws IOException{
File dest = new File(destPath);
if(dest.isFile()||dest.isDirectory()){
System.out.println("無法存儲到已有文件或文件夾中中,請指定未建立的文件夾路勁");//爲方便合併,限定必須爲未建立的文件夾路徑
return;
}
if(!dest.exists()){
dest.mkdirs();
}
long head=0;
long size=this.blockSize;
for(int i=0;i<blocks;i++){
if(i==blocks-1){
size=this.fileSize-head;
}
splitDtails(i,dest,head,size);
head+=size;
}
/**
* 輸出分割信息
* 由於分割信息名制定
* 所以限定未建立的文件夾
* 以便合併時讀取
*/
File info = new File(dest,"splitInfo");
DataOutputStream dos = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream(info)));
dos.writeUTF(this.name);
dos.writeInt(this.blocks);
dos.flush();
dos.close();
}
private void splitDtails(int idx,File dest,long head,long size) throws IOException{
File destSplit = new File(dest,this.name+"第"+idx+"部分");
if(destSplit.exists()){
destSplit.delete();
}//避免重複寫入
RandomAccessFile is = new RandomAccessFile(src,"r");
OutputStream os = new BufferedOutputStream(new FileOutputStream(destSplit,true));
is.seek(head);
byte[] flush =new byte[1024];
int len=0;
long sum=0;
//此處要尤爲注意,應按實際size寫入,最後一次
//同文件複製不同,此處無法通過返回-1來推出循環
//因爲文件分割所以在size邊界外還是有字節存在
//若直接使用len,就無法正確讀取!
while(-1!=(len=is.read(flush))){
if(size-len>=0){
os.write(flush, 0, len);
size-=len;
}else{
os.write(flush,0,(int)size);
break;
}
}
os.flush();
os.close();
is.close();
}
/**、
* 通過制定大小來分割文件
* @param destPath
* @param blockSize
* @throws IOException
*/
public void splitBySize(String destPath,long blockSize) throws IOException{
if(blockSize>fileSize){
blockSize = fileSize;
}
this.blockSize=blockSize;
this.blocks = (int)(Math.ceil((fileSize*1.0/blockSize)));
split(destPath);
}
public static void main(String[] args) {
FileSplit fs = new FileSplit("G:/《Java核心技術 卷1 基礎知識(原書第9版)》(完整中文版).pdf");
try {
fs.split("G:/test");
} catch (IOException e) {
e.printStackTrace();
}
}
}
文件的合併
package fileSplitAndBination;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class FileBination {
private String srcPath;
private String destPath;
private String fileName;
private int blocks;
public FileBination(String srcPath, String destPath) throws IOException {
this.srcPath = srcPath;
this.destPath = destPath;
binationIntial();
}
public void binationIntial() throws IOException{
File src = new File(srcPath);
File splitInfo = new File(src,"splitInfo");
if(!src.isDirectory()){
System.out.println("請提供分割文件絕對路徑!");
return;
}else if(!splitInfo.exists()||!splitInfo.isFile()){
System.out.println("分割信息文件不存在或損壞");
return;
}else{
DataInputStream dis = new DataInputStream(
new BufferedInputStream(
new FileInputStream(splitInfo)));
this.fileName=dis.readUTF();
this.blocks = dis.readInt();
}
}
public void bination() throws IOException{
File bFile = new File(destPath, fileName);
for(int i=0 ;i<blocks;i++){
if(!binationDtail(bFile,i)){
bFile.delete();
break;
}
}
}
private boolean binationDtail(File bFile,int i) throws IOException{
File inFile = new File(srcPath,fileName+"第"+i+"部分");
OutputStream os = new BufferedOutputStream(new FileOutputStream(bFile,true));
InputStream is=null;
boolean ok=true;
if(!inFile.exists()){
System.out.println("第"+i+"個分割文件損壞");
ok=false;
}else{
is = new BufferedInputStream(new FileInputStream(inFile));
int len =0;
byte[] flush = new byte[1024];
while(-1!=(len=is.read(flush))){
os.write(flush, 0, len);
}
}
os.flush();
os.close();
is.close();
return ok;
}
public static void main(String[] args) {
try {
FileBination fb =new FileBination("G:/test","D:/");
fb.bination();
} catch (IOException e) {
e.printStackTrace();
}
}
}