1. 程式人生 > >java 實現大檔案分隔成多個小檔案

java 實現大檔案分隔成多個小檔案

public class FileTest {

    /**
      * 檔案分隔器:給定檔案的路徑和每一塊要拆分的大小,就可以按要求拆分檔案
      * 如果指定的塊給原檔案都還要大,為了不動原檔案,就生成另一個檔案,以.bak為字尾,這樣可以保證原檔案
      * 如果是程式自動拆分為多個檔案,那麼字尾分別為".part序號",這樣就可以方便檔案的合併了
      * 原理:很簡單,就是利用是輸入輸出流,加上隨機檔案讀取。
      */
    String FileName=null;//原檔名
    long FileSize=0;//原檔案的大小
    long BlockNum=0;//可分的塊數

    /**
     * @param fileAndPath 原檔名及路徑
    */
    private void getFileAttribute(String fileAndPath)//取得原檔案的屬性
    {
        File file=new File(fileAndPath);
        FileName=file.getName();
        FileSize=file.length();
    }
    /**
    *
    * @param blockSize 每一塊的大小
    * @return 能夠分得的塊數
    */
    private long getBlockNum(long blockSize)//取得分塊數
    {
        long fileSize=FileSize;
        if(fileSize<=blockSize)//如果分塊的小小隻夠分一個塊
        return 1;
        else {
            if(fileSize%blockSize>0) {
                return fileSize/blockSize+1;
            } else
                return fileSize/blockSize;
        }
    }
    /**
    *
    * @param fileAndPath 原檔案及完整路徑
    * @param currentBlock 當前塊的序號
    * @return 現在拆分後塊的檔名
    */
    private String generateSeparatorFileName(String fileAndPath,int currentBlock)//生成折分後的檔名,以便於將來合將
    {
        return fileAndPath+".part"+currentBlock;
    }
    /**
    *
    * @param fileAndPath 原檔案及完整路徑
    * @param fileSeparateName 檔案分隔後要生成的檔名,與原檔案在同一個目錄下
    * @param blockSize 當前塊要寫的位元組數
    * @param beginPos 從原檔案的什麼地方開始讀取
    * @return true為寫入成功,false為寫入失敗
    */
    private boolean writeFile(String fileAndPath,String fileSeparateName,long blockSize,long beginPos)//往硬碟寫檔案
    {
        RandomAccessFile raf=null;
        FileOutputStream fos=null;
        byte[] bt=new byte[1024];
        long writeByte=0;
        int len=0;
        try {
            raf = new RandomAccessFile(fileAndPath,"r");
            raf.seek(beginPos);
            fos = new FileOutputStream(fileSeparateName);
            while((len=raf.read(bt))>0) {
                if(writeByte<blockSize)//如果當前塊還沒有寫滿
                {
                    writeByte=writeByte+len;
                    if(writeByte<=blockSize)
                        fos.write(bt,0,len);
                    else {
                        len=len-(int)(writeByte-blockSize);
                        fos.write(bt,0,len);
                    }
                }
            }
            fos.close();
            raf.close();
        } catch (Exception e) {
            e.printStackTrace();
            try {
                if(fos!=null)
                    fos.close();
                if(raf!=null)
                raf.close();
            } catch(Exception f)
            {
                f.printStackTrace();
            }
            return false;
        }
        return true;
    }
    /**
    * @param fileAndPath 原文路徑及檔名
    * @param blockSize 要拆分的每一塊的大小
    * @return true為拆分成功,false為拆分失敗
    */
    private boolean separatorFile(String fileAndPath,long blockSize)//折分檔案主函式
    {
        getFileAttribute(fileAndPath);//將檔案的名及大小屬性取出來
        //System.out.println("FileSize:"+FileSize);
        //System.out.println("blockSize:"+blockSize);
        BlockNum=getBlockNum(blockSize);//取得分塊總數
        //System.out.println("BlockNum:"+BlockNum);
        //System.exit(0);
        if(BlockNum==1)//如果只能夠分一塊,就一次性寫入
            blockSize=FileSize;
        long writeSize=0;//每次寫入的位元組
        long writeTotal=0;//已經寫了的位元組
        String FileCurrentNameAndPath=null;
        for(int i=1;i<=BlockNum;i++)
        {
            if(i<BlockNum)
                writeSize=blockSize;//取得每一次要寫入的檔案大小
            else
                writeSize=FileSize-writeTotal;
            if(BlockNum==1)
                FileCurrentNameAndPath=fileAndPath+".bak";
            else
                FileCurrentNameAndPath=generateSeparatorFileName(fileAndPath,i);
            //System.out.print("本次寫入:"+writeSize);     
            if(!writeFile(fileAndPath,FileCurrentNameAndPath,writeSize,writeTotal))//迴圈往硬碟寫檔案
                return false;
            writeTotal=writeTotal+writeSize;
            //System.out.println("  總共寫入:"+writeTotal);
        }
        return true;
    }

    public static void main(String[] args)
    {
        FileTest separator = new FileTest();
        String fileAndPath="f://abc.txt";//檔名及路徑
        long blockSize=200*1024;//每一個檔案塊的大小,大小是按位元組計算
        if(separator.separatorFile(fileAndPath,blockSize)) {
            System.out.println("檔案折分成功!");
        }
        else {
            System.out.println("檔案折分失敗!");
        }
    }


}