好吧,既然演算法這個高深的問題還不能遊刃有餘,那就先鞏固鞏固基礎吧!
我就根據自己的學習經曆,來複習一下以前學過的知識吧!
首先聲明,這些概念非本人創造,是本人學習過程中接觸到的。然後我根據自己的理解空閑時間獨立完成。所有原始碼全部是自己原創!這都是站在巨人肩膀上的結果
今天寫個檔案切割器:
檔案切割器就是把把一些大檔案切割成相同大小(尾巴除外)的子檔案。為什麼要這麼做呢?這是因為在一些論壇等網站由於伺服器效能等原因,上傳的檔案大小一般是不能超過一定大小的。我們為了上傳一些大檔案,就不得不把這些大檔案切割成一份一份的小檔案,使用者下載下來之後可以合并還原成原來的檔案。
檔案切割器涉及的一些核心東西就是Java的IO流,因為檔案儲存體在硬碟上,一般情況下,要切割的檔案可能是一些視頻流或者音頻流檔案,所以一般要用到位元組流。要將檔案從硬碟讀到記憶體,很明顯就要用到FileInputStream 這個流對象。因為我們要按指定的大小來切割檔案,所以就應該手動定義緩衝區,所以就不對這個流進行封裝了。
如何將一個大的檔案流放到小的檔案流中呢?這裡就要用到一個迴圈了,每一次把緩衝區的資料及時刷到FileOutputStream中去,並對檔案命名。
關於檔案的命名,為了不覆蓋前一次的資料,我們可以使用一個唯一的資料來命名,這就想到了時間戳記。可以對系統目前時間的毫秒值進行擷取來命名,如果覺得資料大了可以將其取餘。還有一種簡單的方法,那就是搞一個計數器,用原檔案檔案名稱+計數序號作為片段檔案檔案名稱。這種方式也可以。而且更加具有實用性。所以我的用這主。關於檔案尾碼名,其實Window中檔案尾碼名只是為了區分不同的應用程式的檔案資料。沒有其他作用。所以這裡的尾碼名可以自訂一個獨特的。不過,一般我們用.part作為尾碼名,通俗易懂。
在切割的過程中要注意一個問題是切割後的合并問題。合并片段檔案就要知道這檔案以前的檔案名稱是什麼,尾碼名是什麼,切割分數有沒有等等這些資訊。所以應該在切割的過程中應該將這些資料存放區到一個檔案當中。因為資料較少且簡單。所以就用一個properties檔案儲存就可以了。
大概的思想就是這樣了,具體實現過程我們直接看源碼:
/** *Mar 28, 2013 *Copyright(c)JackWang *All rights reserve *@Author <a href="mailto:wangchengjack@163.com">JackWang</a>*/package com.myjava.function;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.PrintStream;import java.util.Properties;import com.myjava.myexception.DataErrorException;import com.myjava.myexception.NoSuchFileException;/** * 實現大檔案切割 * 思路:檔案類型不確定,所以應該用位元組流 * 可以自訂緩衝區,緩衝區大小為切割部分大小 * 在將切割後的流存到檔案中 * 應該有一個檔案用於記錄切割資訊,如原始檔案名,切割份數,在合并檔案時讀取這些資訊來確定檔案類型等 * 切割檔案的尾碼名可以自訂,一般用.part * @author WangCheng * */public class SplitFiles {/** * @param args * @throws IOException */public static void main(String[] args) throws IOException {File file = new File("I:"+File.separator+"梁祝.mp3"); //定義檔案對象boolean result = splitFiles(file,1);System.out.println(result);}/** * * @param file 要切割的檔案對象 * @param i 要切割的大小 * @return 切割是否成功 * @throws IOException */public static boolean splitFiles(File file, int i) throws IOException {//參數合法性檢查if(!file.exists()){throw new NoSuchFileException("檔案不存在,請檢查!!");}if(i < 0){throw new DataErrorException("資料不合法!");}//切割檔案存放處File dir = new File("I:"+File.separator+"PartFiles"); //自訂片段檔案存放路徑if (!dir.exists()) {dir.mkdirs();}//建立原檔案流FileInputStream fis = new FileInputStream(file);//建立緩衝區byte[] buff = new byte[1024*1024*i];int len = 0;int count = 0; //記錄切割份數String fileName = getFileName(file.getName());while((len=fis.read(buff))!=-1){FileOutputStream fos = new FileOutputStream(new File(dir,fileName+(++count)+".part"));fos.write(buff, 0, len);fos.close();}//記錄檔案資訊recordFileInfo(file.getName(),count);fis.close();return true;}public static void recordFileInfo(String fileName, int count) throws FileNotFoundException, IOException {Properties prop = new Properties();File countFile = new File("I:"+File.separator+"PartFiles",getFileName(fileName)+".properties");prop.setProperty("fileName", fileName);prop.setProperty("count", count+"");PrintStream out = new PrintStream(countFile);prop.store(out, "sava file Infomation");//prop.list(System.out);}public static String getFileName(String fileName) {return fileName.substring(0,fileName.indexOf("."));}}
關於代碼中拋出的自訂異常,我定義了一個異常包,繼承了RuntimeException類,沒啥技術含量,就不貼了!
好了,到此為止就完成了檔案切割器的核心代碼。歡迎大家批評和指導!
明天上檔案合并器!