sequentially reading a structs from binary file in C++

最后都变了- 提交于 2020-01-05 08:06:52

问题


I'm trying to write a program, when the program is performing an operation (Example: search, update, or add), it should be direct access. The program should not read all the records sequentially to reach a record.

 #include <iostream>
#include <fstream>
#include <string>

using namespace std;

struct Student{
    int Id;
    int Money;
    int Age;
    char name[15];
};

void main(){
    Student buffer;
    ofstream BinaryFile("student", ios::binary);
    ifstream WorkerText("worker.txt");

//-------------------------------------------------------------------------------------------------------------
    while( WorkerText.good() ){                     
        WorkerText>> buffer.Age >> buffer.name >> buffer.name >> buffer.name;
        BinaryFile.write(  (char *) &buffer, sizeof(Student)  );    

    }
    BinaryFile.close();
//-------------------------------------------------------------------------------------------------------------
    ifstream ReadBinary( "student", ios::binary | ios::out );
    while( BinaryFile.good() ){                     
        ReadBinary.read((char*)&buffer,sizeof(Student));
        cout<<buffer.Age;

    }


//-------------------------------------------------------------------------------------------------------------


system("pause");
}

I stucked here I could not read sequentially how can I solve this


回答1:


You can skip sequential read only if the file contains structures of the same size, or uses some index table.

For the case of structures of same size:

void ReadStudent(istream &src, Student &dst)
{
    src.read(&dst, sizeof(dst));
}

void GoToStudentIndex(istream &src, size_t idx)
{
   src.seekg(idx * sizeof(Student), is.beg);
 }

The functions above assume you are writing data as follows:

void WriteStudent(ostream &dst, const Student &src)
{
    dst.write(&src, sizeof(src));
}



回答2:


You are using "out" mode when you open the student file for input:

ifstream ReadBinary( "student", ios::binary | ios::out );  
^^^^^^^^                                      ^^^^^^^

Try this:

ifstream ReadBinary("student", ios::binary);  

The ifstream constructor already opens the file in input mode (ios::in).




回答3:


There are three options to avoid sequential reads:

  1. Have delimited records, store them sorted by key and use bisection
  2. Have fixed size records, store them sorted by key and use bisection
  3. Have separate index file (key => offset in the data file) of much smaller size than the data file, preload it first and use for direct read by the offset.



回答4:


When we want to do search (and subsequent update) but store records in flat file sequentially, you need to have external index to help you get direct access to desired record ! Say in this case you want to search student by name and then update record, you can do some thing like this:

// Store in map name and the position of record
std::map name2offset;

void writeRecord(const Student& student)
{
    name2offset[string(student.name)]=BinaryFile.tellp();
    BinaryFile.write(reinterpret_cast<char*>(&student), sizeof(Student));
}

// Return true if updated successfully else false.
bool update(const string& name, Student &newRecord)
{
    std::map<char,long>::iterator itr = name2offset.find(name);
    if (itr != name2offset.end()) {
        BinaryFile.seekp(itr->second);
        BinaryFile.write(reinterpret_cast<char*>(&newRecord), sizeof(Student));

        return true;
    }

    return false;
}

These all assume that your struct is fixed size one (which it is in your example).



来源:https://stackoverflow.com/questions/15452311/sequentially-reading-a-structs-from-binary-file-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!