2010-01-12 30 views
13

Intento escribir y leer el objeto de clase en y desde el archivo binario en C++. No quiero escribir el miembro de datos individualmente, sino que escribo todo el objeto a la vez. Para un ejemplo simple:Escribir y leer el objeto de clase en y desde el archivo binario

class MyClass { 
public: 
    int i; 

    MyClass(int n) : i(n) {} 
    MyClass() {} 

    void read(ifstream *in) { in->read((char *) this, sizeof(MyClass)); } 
    void write(ofstream *out){ out->write((char *) this, sizeof(MyClass));} 
}; 

int main(int argc, char * argv[]) { 
    ofstream out("/tmp/output"); 
    ifstream in("/tmp/output"); 

    MyClass mm(3); 
    cout<< mm.i << endl; 
    mm.write(&out); 

    MyClass mm2(2); 
    cout<< mm2.i << endl; 
    mm2.read(&in); 
    cout<< mm2.i << endl; 

    return 0; 
} 

Sin embargo, el programa de salida de funcionamiento que el valor de mm.i supuestamente escribe en el archivo binario no se lee y se asigna a mm2.i correctamente

$ ./main 
3 
2 
2 

Así que lo que está mal ¿con eso?

¿Qué debo tener en cuenta cuando generalmente escribo o leo un objeto de una clase en o desde un archivo binario?

Respuesta

11

Los datos se almacenan en el búfer por lo que no han llegado al archivo cuando lo va a leer. Dado que usa dos objetos diferentes para hacer referencia al archivo de entrada/salida, el sistema operativo no tiene idea de cómo están relacionados.

Necesitas o bien eliminar el archivo:

mm.write(&out); 
out.flush() 

o cerrar el archivo (que hace un rubor implícita):

mm.write(&out); 
out.close() 

También puede cerrar el archivo haciendo que el objeto salga del alcance:

int main() 
{ 
    myc mm(3); 

    { 
     ofstream out("/tmp/output"); 
     mm.write(&out); 
    } 

    ... 
} 
+0

Gracias! ¿Es posible definir un solo objeto para la escritura de archivos y la lectura en C++? Recuerdo que es posible en C. – Tim

+0

@Tim.Por ejemplo, puede tener una secuencia de archivos abierta para leer y escribir. –

+0

En mi opinión, la respuesta de Yann Ramin es mucho más útil. Él explica esta idea de enrojecimiento, y también indica una mejor manera con el impulso. – MeM

1

Mi C++ es bastante oxidado y muy poco probado, pero es posible que desee echar un vistazo a Serialización y Deserialización. FAQ

9

Dumping los datos en bruto es una idea terrible, desde múltiples ángulos. Esto empeorará una vez que agregue los datos del puntero.

Una sugerencia sería usar Boost.Serialization que permite un volcado de datos mucho más robusto.

Su problema principal es que el archivo aún no contiene el contenido debido al almacenamiento intermedio de fstream. Cierre o limpie el archivo.

2

Voy a repetir "no deberías estar haciendo esto". Si imprime sizeof(myc) en el código anterior, probablemente sea 4, como era de esperar ... PERO intente cambiar la lectura y escritura para que sea virtual. Cuando lo hice, imprime el tamaño como 16. Esos 12 bytes son tripas internas con valores sensibles — y guardarlos y luego leerlos de nuevo sería como esperar que el valor de un puntero siga siendo bueno si lo escribió y lo cargó de nuevo.

Si desea eludir la serialización y asignar la memoria de objeto C++ directamente al disco, existen formas de hackear eso. Pero las reglas están involucradas y no es para los débiles de corazón. Ver POST++ (Persistent Object Storage for C++) como un ejemplo.

Agregaré que no ha marcado el estado fail() o eof(). Si lo hubieras hecho, hubieras sabido que estabas haciendo un uso indebido de la API de Fstream. Inténtelo de nuevo con:

void read(ifstream *in) { 
    in->read((char *) this, sizeof(myc)); 
    if (in->fail()) 
     cout << "read failed" << endl; 
} 
void write(ofstream *out){ 
    out->write((char *) this, sizeof(myc)); 
    if (out->fail()) 
     cout << "write failed" << endl; 
} 

... y vea qué pasa.

Cuestiones relacionadas