2011-03-06 90 views

回答

1

我想對想要編寫自己的實現的解釋可能是好奇心。

無論您是否添加壓縮,如果您只是想將文件存儲在檔案中,類似於tar命令,那麼您有幾種可能的方法。

您必須做出的基本選擇之一是:如何劃分檔案中壓縮文件的邊界?使用特殊字符並不是一個好主意,因爲打包文件可能包含任何開頭的字符。

要跟蹤文件的結尾,可以使用文件的長度(以字節爲單位)。例如,對於每個文件,您可以:

  1. 在檔案中寫入命名打包文件的'\ 0'終止的C字符串。
  2. 寫入存檔一個off64_t,它給出打包文件的長度(以字節爲單位)。
  3. 將打包文件的實際字節(如果有)寫入存檔。
  4. (可選)將歸檔文件的校驗和或CRC寫入歸檔。

對每個文件重複執行此操作,並將結果連接起來而不插入字符。

最後,當沒有文件時,寫一個空的C字符串,一個零字符。

拆包過程是:

  1. 閱讀「\ 0'結尾的C字符串,這個名字打包文件。
  2. 如果名稱爲空,則聲明我們已經讀取了整個存檔,然後退出。
  3. 閱讀提供打包文件長度的off64_t。
  4. 從存檔中讀取與打包文件長度一樣多的字節並寫入新創建的解壓縮文件。

再次重複這些步驟,直到步驟(2)結束程序。

這種設計中文件名與文件數據交替是可行的。它有一些缺點。基本問題是數據結構不是爲隨機訪問而設計的。爲了獲取檔案「中間」的文件信息,需要一個程序來處理前面的文件。程序可以調用lseek_64跳過讀取不需要的程序數據,但處理器至少需要讀取每個文件名和每個文件長度。文件長度是跳過文件數據所必需的。在我排列數據時,必須讀取文件名以查找文件長度。

所以這是低效的。即使不必爲了訪問文件大小而讀取文件名,文件詳細信息被分散到整個存檔中的事實意味着讀取索引數據需要訪問磁盤上的多個範圍的數據。

更好的方法是將索引數據的「塊」寫入文件的前面。此數據結構可能類似於:

  1. 存檔中第一個文件的大小。
  2. 存檔中第一個文件的名稱。
  3. 位於此歸檔中的位置(以字節爲單位),其中「第一個文件」可能位於連續的字節塊中。
  4. 在歸檔中的第二個文件的大小...

和索引中的數據可能會重複,直到再次空名稱的文件標誌着索引的結束。

擁有這樣的索引很不錯,但會帶來一個難題:當用戶希望將文件附加到存檔時,索引可能需要增加大小。這可能會改變壓縮文件在壓縮文件中的位置 - 壓縮文件可能需要將它們移動以爲更大的索引騰出空間。

文件結構可以變得越來越複雜,以滿足所有這些不同的需求。例如,可以將索引設計爲始終從文件系統認爲的「頁面」(操作系統從磁盤讀取或寫入最小大小顆粒的量)中分配索引,並且如果索引需要增長,不連續的「索引頁」通過從一個索引頁導向另一個索引頁的文件位置數據鏈接在一起。 (就像鏈接列表一樣,但在磁盤上。)複雜性可以繼續下去。

0

我一對夫婦一天前寫像程序的焦油,在這裏我實現(希望你能得到一些想法): 每個文件都存儲在文件歸檔與「頭」,這是這樣的:

<file-type,file-path,file-size,file-mode> 

在文件類型中,我使用0代表文件,使用1代表目錄(通過這種方式,您可以重新創建目錄樹) 例如,名爲foo.txt的文件頭大小爲245字節,模式爲0755 unix,看到chmod)將看起來像:

<0,foo.txt,245,0755> 
here the file contents 

以這種方式,文件存檔的第一個字符總是<,然後解析由逗號分隔的列表(第一個可能的錯誤)並提取文件類型,路徑,大小(您將使用它來讀取下一個大小字節從檔案 - 避免「特殊字符錯誤」由Heath Hunnicutt指出)和文件的模式(假設你有一個二進制文件,並且你也想在提取它時執行它,你需要用原始文件模式chmod它)。

關於第一個可能的錯誤,逗號不常用於文件名中,但最好使用另一個字符或「用一對夫婦」消毒路徑「」(對不起,我現在不記得名字,而英語不是我的母語),顯然解析器應該知道它,並忽略「」中的任何逗號。

對於在C中編寫和讀取文件,請參閱stdio中的fgetc和fputc。h 要獲取文件信息,chmod和目錄樹可以從sys/stat.h中看到stat和chmod,從ftw.h中看到ftw(可能是linux/unix,因爲是系統調用)。

希望它有幫助! (如果你需要一些代碼我可以發佈一些片段,頭文件解析可能是最難的部分)。