压缩二进制文件

Compressing the binary file

本文关键字:二进制文件 压缩      更新时间:2023-10-16

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

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

文件压缩后,它看起来像这样:1 2 3 4 x x x x

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

**知道如何在代码中实现这个吗?也许seek函数会有用。* *

     // 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:nn";
    // 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;
}

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

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

。在Linux上,您可以在文件中创建文件系统,然后挂载它。然后,您可以为每个人创建一个文件并将其保存在文件系统中。这样,你(几乎)肯定没有错误,并收到安全更新。

如果你不是在Linux上,你可以使用一些文件系统(NTFS, EXT4…)c++ api来直接使用文件系统。

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

最后:如果你的文件非常小,那么我认为你实际上根本不需要碎片整理