c ++: trabajando con bytes
Frecuentes
Visto 2,461 veces
3
Mi problema es que necesito cargar un archivo binario y trabajar con bits individuales del archivo. Después de eso, necesito guardarlo como bytes, por supuesto.
Mi principal problema es: ¿en qué tipo de datos elegir trabajar: char o long int? ¿Puedo de alguna manera trabajar con caracteres?
6 Respuestas
6
A menos que el rendimiento sea una misión crítica aquí, use lo que haga que su código sea más fácil de entender y mantener.
respondido 09 mar '12, 14:03
Ignore mi respuesta, esta es la regla # 1: Daramarak
+1 Y no reinventes la rueda si es posible, si no tienes que trabajar con un formato de serialización predefinido, no te inventes uno. - KillianDS
De acuerdo, aunque es muy divertido reinventar la rueda. "Mira, el mio es cuadrado" - Daramarak
Es posible que una pregunta aclarada pueda invitar a una recomendación más detallada. Sin embargo, no me queda claro que esto deba ser pensado demasiado a partir de la información disponible. - Steve Townsend
5
Antes de comenzar a codificar cualquier cosa, asegúrese de entender Endianess, tamaños de letra c++, Y cómo extrañas puede ser que sean.
EL unsigned char
es el único tipo que tiene un tamaño fijo (byte natural de la máquina, normalmente 8 bits). Entonces, si diseña para la portabilidad, es una apuesta segura. Pero no es difícil simplemente usar el unsigned int
o incluso un long long
para acelerar el proceso y utilizar size_of
para averiguar cuántos bits está obteniendo en cada lectura, aunque el código se vuelve más complejo de esa manera.
Debe saber que para una verdadera portabilidad, ninguno de los tipos internos de c ++ es fijo. Un carácter sin firmar puede tener 9 bits y el int puede ser tan pequeño como en el rango de 0 a 65535, como se indica en este y este https://www.youtube.com/watch?v=xB-eutXNUMXJtA&feature=youtu.be
Otra alternativa, como sugiere user1200129, es usar el aumentar la biblioteca de enteros para reducir todas estas incertidumbres. Esto es si tiene impulso disponible en su plataforma. Aunque si busca bibliotecas externas, hay muchas bibliotecas de serialización para elegir.
Pero antes que nada, incluso antes de comenzar a optimizar, haga algo simple que funcione. Luego, puede comenzar a crear perfiles cuando comience a experimentar problemas de tiempo.
contestado el 23 de mayo de 17 a las 13:05
Sí, el mundo de la programación se vuelve extraño una vez que comienzas a explorar plataformas alienígenas;) - Daramarak
Puede usar boost integer.hpp para tipos de int portátiles. Por ejemplo, si necesita asegurarse de obtener 64 bits firmados, puede usar boost::int64_t en diferentes compiladores y sistemas operativos y siempre obtendrá el tipo que espera. Esto es especialmente importante cuando necesita reinterpretar_cast datos. - 01100110
3
Realmente solo depende de lo que quieras hacer, pero diría que, en general, la mejor velocidad será mantener el tamaño de los números enteros en los que está compilado tu programa. Entonces, si tienes un programa de 32 bits, elige 32 enteros de bits, y si tiene 64 bits, elija 64 bits.
Esto podría ser diferente si hay algunos bytes en su archivo o si hay números enteros. Sin conocer la estructura exacta de su archivo, es difícil determinar cuál es el valor óptimo.
respondido 09 mar '12, 14:03
1
Sus oraciones no son realmente correctas en inglés, pero en la medida en que puedo interpretar la pregunta, puede usar mejor el tipo de carácter sin firmar (que es un byte) para poder modificar cada byte por separado.
Editar: cambiado según el comentario.
respondido 09 mar '12, 14:03
¿Qué es un byte sin firmar? byte es un carácter sin firmar. - MByD
Ahora es un inglés algo correcto. :) - Profesor Falken
Como no existe una definición para byte
en C, no puedes decir si está firmado o no. - Señor lister
@Michel, lo editaste al revés. estabas buscando unsigned char
. - Señor lister
Fijo (Síndrome de los viernes por la tarde) - michel keijzers
1
Si está tratando con bytes, la mejor manera de hacerlo es usar un tipo de tamaño específico.
#include <algorithm>
#include <iterator>
#include <cinttypes>
#include <vector>
#include <fstream>
int main()
{
std::vector<int8_t> file_data;
std::ifstream file("file_name", std::ios::binary);
//read
std::copy(std::istream_iterator<int8_t>(file),
std::istream_iterator<int8_t>(),
std::back_inserter(file_data));
//write
std::ofstream out("outfile");
std::copy(file_data.begin(), file_data.end(),
std::ostream_iterator<int8_t>(out));
}
EDITAR error solucionado
respondido 09 mar '12, 14:03
No se garantiza que uint8_t esté definido para todos los sistemas. Pero establece mucho más claramente la intención del uso. - Daramarak
El estándar C99 existe desde hace mucho tiempo y casi todos los sistemas tienen <stdint.h>
. (Honestamente, no puedo pensar en uno que no lo haga. Es uno de los encabezados más fáciles de proporcionar). El equivalente de C ++ podría no estar allí, pero eso se soluciona fácilmente. - mike de simone
1
Si necesita hacer cumplir cuántos bits hay en un tipo entero, debe usar el <stdint.h>
encabezamiento. Está presente tanto en C como en C++. Define el tipo como uint8_t
(entero sin signo de 8 bits), que se garantiza que se resolverán en el tipo adecuado en la plataforma. También les dice a otros programadores que leen su código que la cantidad de bits es importante.
Si le preocupa el rendimiento, es posible que desee utilizar los tipos de más de 8 bits, como uint32_t
. Sin embargo, al leer y escribir archivos, deberá prestar atención a la Endianess de su sistema En particular, si tiene un ascendente hacia la izquierda sistema (por ejemplo, x86, la mayoría de ARM), entonces el valor de 32 bits 0x12345678
se escribirá en el archivo como los cuatro bytes 0x78 0x56 0x34 0x12
, mientras que si tienes un big endian (por ejemplo, Sparc, PowerPC, Cell, algunos ARM e Internet), se escribirá como 0x12 0x34 0x56 0x78
. (igual va o lectura). Por supuesto, puede trabajar con tipos de 8 bits y evitar este problema por completo.
respondido 09 mar '12, 14:03
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas c++ io numbers or haz tu propia pregunta.
Por cierto, ¿cuánto tiempo es su archivo? ¿Es realmente necesario pensar ya en la optimización? ¿Y tiene que cambiar bytes individuales o son trozos de bytes de "bits individuales"? - Michel Keijzers
@Deepak: Usar ints para analizar datos binarios es solo pedir problemas de endianness. - KillianDS
Depende de las operaciones que quiera hacer, ANDing 8 caracteres es igual a una operación int. (x64) - Deepak
Deepak:
sizeof(long int)
no siempre es lo mismo quesizeof(int)
. Ciertamente no está en la configuración en la que estoy escribiendo esto. - Peter@Deepak: cuando es lo mismo, ¿por qué sizefo(long int) != sizeof(int) aquí? - PlasmaHH