Read saved objects in .dat file

3

How do I get the read function to read arquivo.dat every time I start the program? I'm writing objects to a file, and I need to read them every time the program starts.

Problem: I'm having segmentation failure issues when trying to read this data already saved.

void DataManip::DataManipWrite(DateAdress *writer) {

    ofstream ObjectWriter;
    ObjectWriter.open("dbaddress.dat", ios::binary);    
    ObjectWriter.write((char *)&writer, sizeof(writer));
    ObjectWriter.close();

}

void DataManip::DataManipRead(DateAdress *reader) {

    ifstream ObjectReader;
    ObjectReader.open("dbaddress.dat", ios::binary);    
    ObjectReader.read((char *)&reader, sizeof(reader));
    ObjectReader.close();

}
    
asked by anonymous 25.12.2014 / 17:31

3 answers

4

You can not write objects and then read them into memory. You need to serialize them.

In fact you are trying to serialize when you use cast (char *) but it does not give you the result you expect.

In general you should save this data as text. Not that it can not be binary, but you will have to create a format for that binary. Do not just play any information there. In the text it also needs a format but it is easier because it has some obvious and simple to manipulate.

Just because a file is considered binary does not mean you can play binary code or direct memory information. This binary means that the data there should be treated by byte and should not consider anything specific in it. It should be treated as a sequence of bytes and the program should know how to handle them.

In a text file there are some assumptions such as the existence of a line break.

Because C ++ does not have its own functionality in its library that facilitates serialization. There are third-party libraries for this.

The first recommendation I make is to write to text file. Unless you really need it to be binary and you want to handle the complexity of doing it.

The second is to prepare a form whether serialization to write and deserialization after reading.

The first one will take each member of type DateAdress and transform it into a sequential text that can be written to the file. Note that you may need to do some conversions on numeric types and especially on types that are actually pointers. You can not write the pointer, you have to write the data that the pointer points to (this includes a recursive process) or some identification so that one information is later associated with another one correctly (this is not easy to do correctly). When reading this serialized data in the file you have to do the reverse process, interpret every information in the text according to its size or through special markers (if you keep the order of the fields), or you know identifiers for each field there is no need to keep order, an example of this is the JSON format). Taking each information individually you can put in the right member of type DateAdress , doing the necessary conversions.

Is it complicated? IS. Is there a better way? I do not know.

I just want to stress that eventually a binary file might be more useful, the big difference is that you will have to understand the content without any help from the standard adopted in texts.

The error occurs because in the background you are throwing dirt in memory.

The cast you used is not recommended in C ++. I'm not saying it will work but it would help if I had done reinterpret_cast<const char*>(&writer) . I can not test here but I do not know if it would apply to reader . That's just an idea.

I'm not saying that what you're doing can not work, just that it's a beauty of a gambiarra. I'll even suggest a change that might solve your situation if the DateAdress type is simple enough. Note that it may work but it is a fragile solution.

Read the data individually instead of reading the entire structure:

ObjectReader.read((char *)&reader.campo1, sizeof(reader.campo1));
ObjectReader.read((char *)&reader.campo2, sizeof(reader.campo2));
ObjectReader.read((char *)&reader.campo3, sizeof(reader.campo3));

As I do not know the type composition, I kicked three names into the fields.

But also to work it may be necessary to "compact" the structure, which is not always desirable. I've never done it, but I know I need to use #pragma :

GCC:

struct __attribute__((packed)) nome { ... };

Microsoft:

#pragma pack(push, 1)
struct nome { ... };
#pragma pack(pop)
    
25.12.2014 / 18:35
1

The error is that you are not writing an object of type DateAddress to the file, but actually a pointer to a DateAddress .

Your .dat file is getting something like:

A4 FE 22 00

4 bytes representing only a pointer to a DateAddress , that is the local variable writer .

Then on the lines where you have:

ObjectWriter.write((char *)&writer, sizeof(writer));
ObjectReader.read((char *)&reader, sizeof(reader));

Should be:

ObjectWriter.write((char *)writer, sizeof(DateAddress));
ObjectReader.read((char *)reader, sizeof(DateAddress));

Although the above code does a very "blind" reading / writing of file data, I think it would be more correct to read / write member per class member.

    
25.12.2014 / 19:15
0
void DataManip::DataManipWrite(DateAdress *writer) {

#define LENGTH 1024
char Directory[LENGTH] = {"Data/"}; 

    ofstream ObjectWriter;
    strcat(Directory, writer->getFamily()); strcat(Directory,".dat");
    ObjectWriter.open(Directory, ios::out | ios::app | ios::binary);    
    ObjectWriter << "#------------------------------#"<< endl;
    ObjectWriter << "Bairro: " << writer->getBairro() << endl;
    ObjectWriter << "Rua: " << writer->getRua() << endl;
    ObjectWriter << "Telefone: " << writer->getTelefone() << endl;
    ObjectWriter << "Numero: " << writer->getNumero() << endl;
    ObjectWriter << "#------------------------------#\n"<< endl;

    ObjectWriter.close();

}

void DataManip::DataManipRead(char Directory[]) {
    string line_text;
    ifstream ObjectReader;
    strcat(Directory,".dat");
    ObjectReader.open(Directory, ios::in | ios::binary);

    if(ObjectReader.is_open() ) {
        while(getline(ObjectReader, line_text)) {
            cout << line_text << endl;
        }

    }   

    ObjectReader.close();

}
    
25.12.2014 / 19:17