from - readfile c++
Insertadores y extractores leyendo/escribiendo datos binarios versus texto (3)
He estado tratando de leer sobre iostremas y entenderlos mejor. Ocasionalmente, me parece importante destacar que los inserters ( <<
) y los extractores ( >>
) están destinados a ser utilizados en la serialización textual . Son algunos lugares, pero este artículo es un buen ejemplo:
http://spec.winprog.org/streams/
Fuera del universo <iostream>
, hay casos en los que << y >> se utilizan de forma similar a una secuencia, pero no obedecen ninguna convención textual. Por ejemplo, escriben datos codificados en binario cuando Qt''s QDataStream
los QDataStream
:
http://doc.qt.nokia.com/latest/qdatastream.html#details
En el nivel de idioma, los operadores << y >> pertenecen a su proyecto para sobrecargarse (por lo tanto, lo que hace QDataStream es claramente aceptable). Mi pregunta sería si se considera una mala práctica para quienes usan <iostream>
usar los operadores << y >> para implementar codificaciones y decodificaciones binarias. ¿Existe (por ejemplo) alguna expectativa de que, si se escribe en un archivo en el disco, el archivo debería ser visible y editable con un editor de texto?
¿Debería uno siempre usar otros nombres de métodos y basarlos en read()
y write()
? ¿O deberían las codificaciones textuales ser consideradas simplemente como un comportamiento predeterminado que las clases integradas con la biblioteca estándar iostream pueden elegir ignorar?
ACTUALIZAR Una cuestión de terminología clave en esto parece ser la distinción de E / S que está "formateada" frente a "no formateada" (en oposición a los términos "textual" y "binario"). Encontré esta pregunta:
escribiendo datos binarios (std :: string) en un std :: ofstream?
Tiene un comentario de @ TomalakGeret''kal diciendo "No me gustaría usar << para datos binarios de todos modos, ya que mi cerebro lo lee como" salida formateada "que no es lo que estás haciendo. De nuevo, es perfectamente válido, pero no confundiría mi cerebro así ".
La respuesta aceptada a la pregunta dice que está bien siempre que uses ios::binary
. Esto parece reforzar el lado del debate "no hay nada de malo" ... pero todavía no veo ninguna fuente autorizada sobre el tema.
La abstracción de los iostreams en el estándar es la de un flujo de datos con formato textual; no hay soporte para ningún formato que no sea de texto. Esa es la abstracción de iostreams. No hay nada de malo en definir una clase de flujo diferente cuya abstracción sea un formato binario, pero hacerlo en una iostream probablemente romperá el código existente y no funcionará.
Los operadores sobrecargados >> y << realizan IO formateado. El resto de las funciones de IO (poner, obtener, leer, escribir, etc.) ejecutan IO sin formato. IO no formateado significa que la biblioteca IO solo acepta un buffer, una secuencia de caracteres sin signo para su entrada. Este búfer puede contener un mensaje de texto o un contenido binario. Es responsabilidad de la aplicación interpretar el búfer. Sin embargo, el IO formateado tomaría en cuenta la configuración regional. En el caso de los archivos de texto, dependiendo del entorno donde se ejecuta la aplicación, puede ocurrir una conversión especial de caracteres en las operaciones de entrada / salida para adaptarlos a un formato de archivo de texto específico del sistema. En muchos entornos, como la mayoría de los sistemas basados en UNIX, no tiene importancia abrir un archivo como un archivo de texto o un archivo binario. Tenga en cuenta que puede sobrecargar el operador >> y << para sus propios tipos. Eso significa que eres capaz de aplicar el IO formateado sin información de configuración regional a tus propios tipos, aunque eso es un poco complicado.
En realidad, los operadores <<
y >>
son operadores de cambio de bit; usarlos para E / S es estrictamente hablando un mal uso. Sin embargo, ese mal uso es tan antiguo como la propia sobrecarga del operador, y la E / S actual es el uso más común de ellos, por lo tanto, son ampliamente considerados como operadores de inserción / extracción de E / S. Estoy bastante seguro de que si no existiera el precedente de iostreams, nadie usaría esos operadores para I / O (especialmente con C ++ 11 que tiene plantillas variadas, resolviendo el problema principal que usa esos operadores resueltos para iostreams, en una manera mucho más limpia). Por otro lado, desde el punto de vista del lenguaje, el operator<<
operator>>
y operator>>
sobrecargado puede significar lo que quiera que signifique.
Entonces la pregunta se reduce a lo que sería un uso aceptable de esos operadores. Para esto, creo que uno tiene que distinguir dos casos: primero, nuevas sobrecargas que trabajan en clases iostream, y segundo, nuevas sobrecargas que trabajan en otras clases, posiblemente diseñadas para funcionar como iostreams.
Consideremos los primeros operadores nuevos en clases iostream. Permítanme comenzar con la observación de que las clases iostream tratan sobre el formateo (y el proceso inverso, que podría denominarse "deformación"; "lexing" en mi humilde opinión no sería el término correcto porque los extractores no determinan el tipo , pero solo trate de interpretar los datos de acuerdo con el tipo dado). Las clases responsables de la E / S real de los datos brutos son los streambufs. Sin embargo, tenga en cuenta que un archivo binario apropiado no es un archivo en el que solo se vuelcan datos brutos internos. Al igual que un archivo de texto (en realidad, más aún), un archivo binario debe tener una codificación bien especificada de los datos que contiene. Especialmente si se espera que los archivos se lean en diferentes sistemas. Por lo tanto, el concepto de salida formateada tiene mucho sentido también para los archivos binarios; solo el formato es diferente (por ejemplo, escribir un número predeterminado de bytes con el más significativo primero para un valor entero).
Los propios iostreams son clases que están destinadas a trabajar en archivos de texto, es decir, en archivos cuyo contenido se interpreta como representación textual de datos. Se optimiza una gran cantidad de comportamiento incorporado para eso y puede causar problemas si se utiliza en archivos binarios. Un ejemplo obvio es que, por defecto, los espacios se omiten antes de intentar cualquier entrada. Para un archivo binario, este sería claramente el comportamiento incorrecto. Además, el uso de configuraciones regionales no tiene sentido para los archivos binarios (aunque se podría argumentar que podría haber una "configuración regional binaria", pero no creo que las configuraciones regionales, tal como se definen para iostreams, proporcionen una interfaz adecuada para eso). Por lo tanto, diría que escribir operator<<
binario operator<<
u operator>>
para clases iostream sería incorrecto.
El otro caso es donde se define una clase separada para entrada / salida binaria (posiblemente reutilizando la capa streambuf para hacer la E / S real). Como ahora estamos hablando de diferentes clases, la argumentación anterior ya no se aplica. Entonces la pregunta ahora es: ¿Deberían el operator<<
y el operator>>
de E / S ser considerados como "operadores de inserción / extracción de texto" o más generalmente como "operadores formateados de inserción / extracción de datos"? Las clases estándar solo las usan para texto, pero no hay clases estándar para la inserción / extracción binaria de E / S, por lo que el uso estándar no puede distinguir entre las dos.
Personalmente diría que la inserción / extracción binaria es lo suficientemente cercana a la inserción / extracción textual que justifica este uso. Tenga en cuenta que también puede hacer manipuladores de E / S binarias significativas, por ejemplo, bigendian
, littleendian
e intwidth(n)
para determinar el formato en el que se van a generar los enteros.
Más allá de eso, también está el uso de esos operadores para cosas que no son realmente E / S (y donde ni siquiera se pensaría en usar la capa streambuf), como leer o insertar en un contenedor. En mi opinión, eso ya constituye un mal uso de los operadores, porque allí los datos no se traducen o salen de un formato diferente. Simplemente se almacena en un contenedor.