2015-09-30 162 views
1

從文件中刪除一條記錄後,有可能是內存中的文件在未使用量曾一度被刪除的記錄佔據。文件中的許多這些已刪除的記錄可能會導致文件變得非常大,但實際上只包含很少有用的數據。有一對夫婦的方式來避免這種情況:壓縮二進制文件

  1. 每當一個新的記錄被插入的文件,它可能在年底插入第一個可用空間在文件中,不一定。但是,如果您在文件中搜索第一個可用空間,這可能會導致效率低下 - 這會使該操作的索引結構無用。您可以維護一個簡單的隊列,該隊列保存已刪除的所有記錄的locationInFile。無論何時需要插入,都可以從隊列中檢索(排隊)元素,並將其用作將新記錄存儲在文件中的位置。 (不要忘記更新索引結構)。
  2. 達到缺失的某個閾值之後(讓我們使用5個缺失例如),二進制文件將被壓縮。這意味着文件中的所有有效記錄將被移至文件的開頭(壓縮到開頭)。考慮下面的圖象,其中每個正方形表示用於在文件中的記錄的地方,每個整數表示有效記錄中使用,並且每個「x」表示已刪除的記錄: 1 XX 2×3 XX 4

後文件的壓縮,它看起來像這樣: 1 2 3 4 xxxxx

請注意,所有有效的記錄都移動到文件的頂部。這種方法需要對索引結構進行重大更新。

**任何想法,我能如何在代碼中實現這一點。也許尋求功能可能會有用。 **

 // This program uses a structure variable to store a record to a file. 
#include <iostream> 
#include <fstream> 
using namespace std; 

// Array sizes 
const int SSN_SIZE = 10, NAME_SIZE = 51, ADDR_SIZE = 51, PHONE_SIZE = 14; 

// Declare a structure for the record. 
struct Info { 
    char ssn[SSN_SIZE]; 
    char name[NAME_SIZE]; 
    int age; 
    char phone[PHONE_SIZE]; 
}; 
int main() { 
    Info person; // To hold info about a person 
    char again; // To hold Y or N 
    // Open a file for binary output. 
    fstream people("people.dat", ios::out | ios::binary); 
    do { 
     // Get data about a person. 
     cout << "Enter the following data about a " << "person:\n"; 
     cout << "SSN: "; 
     cin.getline(person.ssn, SSN_SIZE); 
     cout << "Name: "; 
     cin.getline(person.name, NAME_SIZE); 
     cout << "Age: "; 
     cin >> person.age; 
     cin.ignore(); // Skip over the remaining newline. 
     cout << "Phone: "; 
     cin.getline(person.phone, PHONE_SIZE); 

     // Write the contents of the person structure to the file. 
     people.write(reinterpret_cast<char *>(&person), sizeof(person)); 

     // Determine whether the user wants to write another record. 
     cout << "Do you want to enter another record? "; 
     cin >> again; 
     cin.ignore(); // Skip over the remaining newline. 
    } while (again == 'Y' || again == 'y'); 

    // Close the file. 
    people.close(); 

    people.open("people.dat", ios::in | ios::binary); 

    if (!people) { 
     cout << "Error opening file. Program aborting.\n"; 
     return 0; 
    } 

    cout << "Here are the people in the file:\n\n"; 
    // Read the first record from the file. 
    people.read(reinterpret_cast<char *>(&person), 
     sizeof(person)); 
    // While not at the end of the file, display the records. 
    while (!people.eof()) { 
     // Display the record. 
     cout << "Name: "; 
     cout << person.name << endl; 
     cout << "Age: "; 
     cout << person.age << endl; 
     cout << "Address line 1: "; 
     cout << person.address1 << endl; 
     cout << "Address line 2: "; 
     cout << person.address2 << endl; 
     cout << "Phone: "; 
     cout << person.phone << endl; 

       // Wait for the user to press the Enter key. 
     cout << "\nPress the Enter key to see the next record.\n"; 
     enter code here`cin.get(again); 

      // Read the next record from the file. 
     people.read(reinterpret_cast<char *>(&person), 
     sizeof(person)); 

    } 



     cout << "That's all the data in the file!\n"; 
     people.close(); 
     return 0; 
} 
+0

你的檔案有多大? – NathanOliver

+0

那麼我正在製作一個程序,用於存儲某人的SSN地址名稱和年齡。我需要找到一種方法來刪除記錄的信息,而不會使數據文件變大,因此我必須跟蹤哪些記錄已被刪除。 – JTran

+0

你所描述的通常稱爲碎片整理而不是壓縮。谷歌搜索這個詞可能會提供一些有用的信息。 – mattnewport

回答

0

有你需要思考的問題...您需要確保有目標位置(沒有重疊)足夠的空間,這麼多的事情......

其實這是文件系統的功能,那麼爲什麼要重新發明輪子?

E.g.在Linux上,您可以創建一個文件系統inside a file,然後mount it。然後您可以爲每個人創建一個文件並將其保存在文件系統中。這樣你(幾乎)肯定沒有錯誤並接收安全更新。

如果您不是在Linux上你可能使用一些文件系統(NTFS,EXT4 ...)的C++ API直接使用該文件作爲文件系統。

如果你不喜歡這個主意,我建議重新創建整個文件,然後刪除舊文件。當然,您只能使用未刪除的條目重新創建它。

最後但沒有租約:如果你的文件非常小,那麼我認爲你實際上並不需要碎片整理。