压缩二进制文件

时间:2015-09-30 15:04:09

标签: c++

从文件中删除记录后,文件中可能存在未使用的内存量,该内存曾被删除的记录占用。文件中的许多已删除记录可能导致文件变得非常大但实际上包含的有用数据很少。有几种方法可以避免这种情况:

  1. 每当在文件中插入新记录时,它都可以插入文件的第一个可用空间,而不一定在最后。但是,如果您在文件中搜索第一个可用空间,这可能会导致效率低下 - 这会使索引结构对此操作的有用性无效。您可以维护一个简单的队列,该队列保存已删除的所有记录的locationInFile。每当需要插入时,都可以从队列中检索(排队)元素,并将其用作将新记录存储在文件中的位置。 (不要忘记更新索引结构)。
  2. 达到某个删除阈值后(例如,让我们使用5个删除),将压缩二进制文件。这意味着文件中的所有有效记录都将移动到文件的开头(压缩到开头)。请考虑下面的图片,其中每个方块表示文件中记录的位置,每个整数表示正在使用的有效记录,每个“x”表示已删除的记录: 1 x x 2 x 3 x x 4
  3. 压缩文件后,它看起来像: 1 2 3 4 x x x x x

    请注意,所有有效记录都会移动到文件的顶部。此方法需要对索引结构进行重大更新。

    **我知道如何在代码中实现这一点。也许搜索功能可能很有用。 **

         // 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;
    }
    

1 个答案:

答案 0 :(得分:0)

你需要考虑很多事情......你需要确保在目标位置有足够的空间(没有重叠)......

实际上这是文件系统的功能,为什么要重新发明轮子?

E.g。在Linux上,您可以创建文件系统inside a file,然后创建mount it。然后,您可以为每个人创建一个文件并将其保存在文件系统中。这样你(几乎)肯定没有错误并接收安全更新。

如果你不在Linux上,你可以使用一些文件系统(NTFS,EXT4 ...)c ++ apis直接将文件用作文件系统。

如果您不喜欢这个想法,我建议您重新创建整个文件,然后删除旧文件。当然,您只能使用未删除的条目重新创建它。

最后但没有租约:如果您的文件非常小,那么我认为您根本不需要进行碎片整理。