基本思路:
文件分割:將一個文件分割成若干個獨立的文件。
? ?設置分割后小文件文件的字節數,然后讀取被分割文件,
將對應的字節數寫入分割后的小文件中。
? ? 使用seek定位下一次讀取位置。
文件合并:將分割后的若干的文件合并成一個完整的文件。
按照原有分割順序逐個讀取分割后的小文件,
然后以追加的方式寫入合并的文件中。
?
讀取被分割文件將指定字節數寫入分割后小文件時,下一次讀取時要確保當前讀取位置是上一次的寫入的終點。
例如文件有5000K,設置分割后的文件大小1000K,那么第一次從0開始讀取1000K寫入小文件1,第二次就要從1000開始讀取1000K寫入小文件2.
這時就需要用到seek()不斷設置文件讀取位置。
?
seek是RandomAccessFile類中的函數
構造方法,mode為設置讀寫方法,“”r“為只讀”w”為只寫。
?
?
設置文件指針偏移量,下一次讀或寫時,從當前設置的位置開始。
read,write方法與輸入輸出流函數相同。
?
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.OutputStream; import java.io.RandomAccessFile; import java.util.ArrayList; import java.util.List;public class FileSplit {private String filePath;//文件路徑private long blockSize;//每一塊大小private int blockNum;//塊個個數private List<String> blockName;//每一塊名稱private String [] name;public FileSplit(){this.blockName = new ArrayList<String>();}public FileSplit(String filePath){this(filePath,1024);//未知的尺寸則默認1024 }public FileSplit(String filePath, long blockSize){this();this.filePath = filePath;this.blockSize = blockSize;init();}public String getFilePath() {return filePath;}public void setFilePath(String filePath) {this.filePath = filePath;}public long getBlockSize() {return blockSize;}public void setBlockSize(long blockSize) {this.blockSize = blockSize;}public int getBlockNum() {return blockNum;}public void setBlockNum(int blockNum) {this.blockNum = blockNum;}public List<String> getBlockName() {return blockName;}public void setBlockName(List<String> blockName) {this.blockName = blockName;}private void initBlockName(String destPath){name = new File(filePath).getName().split("\\.");for(int i = 0; i < blockNum; i++){blockName.add(i,destPath + "\\" + name[0] + "_" + i + "." +name[1]);}}public void init(){File src = new File(filePath);//路徑名不存在,或該路徑表示的文件不存,或是文件夾在則結束。if(filePath == null || !src.exists()||src.isDirectory()){return;}if(blockSize >= src.length())this.blockSize = src.length();this.blockNum = (int)Math.ceil(src.length()*1.0/blockSize);}//destPath分割文件存放目錄public void split(String destPath){//分割函數initBlockName(destPath);//初始化分割后的文件名long start = 0;for(int i = 0; i < blockNum; i++){if(i == blockNum - 1)//計算最后一塊大小blockSize = new File(filePath).length()%blockSize;split_m(i,start,blockSize);//參數含義:第i塊,讀取位置,讀取內容大小start += blockSize;//更新起始位置// System.out.println(start); }}//開始分割,每次分割一塊private void split_m(int blockNum,long start,long blockSize){int len = 0;byte[] flush = new byte[1024];RandomAccessFile raf = null;//源文件BufferedOutputStream bos = null;//分割后文件try {bos = new BufferedOutputStream(new FileOutputStream(new File(blockName.get(blockNum))));raf = new RandomAccessFile(new File(filePath),"r");try {raf.seek(start);//確定讀取位置while(-1 != (len = raf.read(flush))){//當前塊分割完成或文件已讀取完跳出循環。//System.out.printf("%d %d %d %s\n",start,blockSize,len,blockName.get(blockNum));if((blockSize - len) >=0){//當前塊大小-寫入字節數,判斷剩余字節bos.write(flush,0,len);//如果塊剩余大小大于讀取字節數,則寫入讀取字節數blockSize -= len;}else{//如果小于,則寫入當前塊剩余字節數bos.write(flush, 0, (int)blockSize);break;//分塊文件已寫滿,跳出當前循環 }}bos.flush();bos.close();raf.close();} catch (IOException e) {// TODO Auto-generated catch block e.printStackTrace();}} catch (FileNotFoundException e) {// TODO Auto-generated catch block e.printStackTrace();}}public void Merge(String mergePath){//合并文件夾路徑int len;byte[] flush = new byte[1024];InputStream is = null;OutputStream bos = null;for(int i = 0; i < blockNum; i++){try {//每次將一個分割后的文件寫入合并文件中。//寫入方法為追加bos = new BufferedOutputStream(new FileOutputStream(new File(mergePath,"merge." + name[1]),true));is = new BufferedInputStream(new FileInputStream(new File(blockName.get(i))));while(-1 != (len = is.read(flush))){//直到被分割的單個小文件讀取完is.read(flush);//將讀取內容放入flushbos.write(flush,0,len);//將讀取內容寫入文件。 }bos.flush();bos.close();is.close();//釋放當前資源,下次讀取下一個小文件。} catch (FileNotFoundException e) {// TODO Auto-generated catch block e.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch block e.printStackTrace();}}} }
public class Main {public static void main(String[] args){FileSplit f = new FileSplit("F:\\依風\\Desktop\\temp.txt",500);//被分割文件,分割后的字節數f.split("F:\\依風\\Desktop");//分割后小文件的存放位置f.Merge("F:\\依風\\Desktop");//合并后大文件的存放位置} }