write read example c++ file fwrite void ofstream

read - ofstream c++



¿Por qué ostream:: write() requiere ''const char_type*'' en lugar de ''const void*'' en C++? (4)

En C / C ++, char es el tipo de datos para representar un byte, por lo que char[] es el tipo de datos natural para datos binarios.

Su pregunta, creo, está mejor dirigida al hecho de que C / C ++ no fue diseñado para tener distintos tipos de datos para "bytes" y "caracteres", en lugar de para el diseño de las bibliotecas de flujos.

La función fwrite() en C usa const void *restrict buffer como el primer argumento, por lo que puede pasar el puntero a su struct como el primer parámetro directamente.
http://en.cppreference.com/w/c/io/fwrite
por ejemplo, fwrite(&someStruct, sizeof(someStruct), 1, file);

Pero en C ++, el ostream::write() requiere const char_type* , lo que obliga a usar reinterpret_cast . (En Visual Studio 2013, es const char* .)
http://en.cppreference.com/w/cpp/io/basic_ostream/write
por ejemplo, file.write(reinterpret_cast<char*>(&someStruct), sizeof(someStruct));

En casi todos los casos, los datos binarios que se van a escribir en los archivos no son una matriz de caracteres, por lo tanto, ¿por qué el estándar prefiere el estilo que parece más complejo?

PD
1. En realidad usé el método write() en ofstream con el modo ios::binary , pero según la referencia, hereda ofstream . Entonces uso ostream::write() arriba.
2. Si desea imprimir un flujo de caracteres, puede usar el operator<<() . ¿El método write() no está diseñado para escribir datos en bruto?
3. Si write() no es la forma de escribir datos binarios, ¿cuál es la forma de hacerlo dentro de la norma? (Aunque esto puede molestar la portabilidad del código debido a varias estrategias de alineación de memoria en diferentes plataformas)


La descripción de esto como una cosa de C vs C ++ es engañosa. C ++ proporciona std::fwrite(const void*, ...) al igual que C. Donde C ++ elige ser más defensivo es específicamente las versiones std::iostream .

"Casi en todos los casos, los datos binarios que se escribirán en archivos no son una matriz de caracteres"

Eso es debatible. En C ++ no es raro que se agregue un nivel de direccionamiento indirecto en E / S, por lo que los objetos se transmiten o se serializan a una forma conveniente, y posiblemente portátil (por ejemplo, endian estandarizado, sin o con relleno de estructura estandarizado) - representación, luego deserialización / analizado al volver a leer. La lógica generalmente se localiza con los objetos individuales involucrados, de modo que un objeto de nivel superior no necesita conocer detalles del diseño de memoria de sus miembros. La serialización y la transmisión tienden a ser pensadas / almacenadas en búfer, etc. en el nivel de byte: se adaptan mejor a los búferes de caracteres, y read() y write() devuelven una cantidad de caracteres que actualmente podrían transmitirse, nuevamente en el carácter y no en el objeto. nivel, por lo que no es muy productivo pretender lo contrario o tendrá un desastre al reanudar las operaciones de E / S parcialmente exitosas.

Las escrituras / lecturas binarias sin procesar realizadas ingenuamente son un poco peligrosas, ya que no manejan estos problemas, por lo que probablemente sea bueno que el uso de estas funciones sea un poco más difícil, ya que reinterpret_cast<> es un poco de olor / advertencia de código.

Dicho esto, un aspecto desafortunado del uso de C char* C ++ es que puede animar a algunos programadores a leer primero una matriz de caracteres, luego usar conversiones inapropiadas para "reinterpretar" los datos sobre la marcha, como un int* dirigido al personaje búfer de una manera que no puede ser alineado adecuadamente.

Si desea imprimir un flujo de caracteres, puede utilizar el operator<<() . ¿El método write() no está diseñado para escribir datos en bruto?

Para imprimir un flujo de caracteres con el operator<<() es problemático, ya que la única sobrecarga relevante tiene un const char* y espera un búfer ''/0'' / terminado en NUL. Eso lo hace inútil si desea imprimir uno o más NUL en la salida. Además, cuando se comienza con un operator<< búfer de caracteres más largo, a menudo sería torpe, detallado y propenso a errores, necesitaría un NUL intercambiado en torno a la transmisión y, a veces, sería un problema importante de rendimiento y / o uso de memoria, por ejemplo, al escribir algunos - pero no el final - de un literal de cadena larga en el que no puede intercambiar un NUL, o cuando el búfer de caracteres puede leerse desde otros subprocesos que no deberían ver el NUL.

La función std::ostream::write(p, n) evita estos problemas, permitiéndole especificar exactamente cuánto desea imprimir.


Ree

Desde el sitio cplusplus.com, la firma de ostream::write es:

ostream& write (const char* s, streamsize n);

Acabo de comprobarlo en VS2013, puedes escribir fácilmente:

std::ofstream outfile("new.txt", std::ofstream::binary); char buffer[] = "This is a string"; outfile.write(buffer, strlen(buffer));


char_type no es exactamente char * , es el parámetro de plantilla del flujo que representa el tipo de carácter del flujo:

template<typename _CharT, typename _Traits> class basic_ostream : virtual public basic_ios<_CharT, _Traits> { public: // Types (inherited from basic_ios): typedef _CharT char_type; <...>

Y std::ostream es solo la instanciación de caracteres:

typedef basic_ostream<char> ostream;