Ir para conteúdo

Como faço para ver e manipular o arquivo binário (os 0 e 1 dos arquivos)?


Kleber Augusto Wilcke

Posts Recomendados

  Boa noite, estou querendo criar um compactador, o algoritmo de compactação já está pronto (depois de 5 anos sempre dando algo errado agora deu certo), o problema é que eu não sei ler e manipular os bytes do arquivo. Pesquisei ofstream e ifstream para o meu intuito, mas na internet só fala de ler campos e variáveis, em nenhum lugar fala de ler os bytes propriamente dito. Por exemplo, eu teria que ler o primeiro byte (01011101) processa-lo com meu algoritmo e escrever um novo byte em um novo arquivo (por exemplo: 01010101) só que não sei manipular bytes puros... só consegui ler e escrever texto.

Link para o comentário
Compartilhar em outros sites

Tem vários caminhos. O primeiro que me vem à mente é criar um buffer e usar a fread() para ler. Usando fopen, fread, fwrite, etc deixará seu programa portável, mas se a intensão é trabalhar em Linux e seus amigos somente, pode usar open(), read(), write() etc.

Na aula 18 do curso Programação Moderna em C eu falo sobre como ler os bytes de um arquivo PE (mas pode ser qualquer outro, claro):

Mas I/O é custoso. Talvez seja interessante você usar funções que leiam o arquivo inteiro para a memória e depois ler de lá. Neste caso eu não sei se tem algo portável, mas na libpe por exemplo, o @jweyrich optou por usar mmap() e a gente compila pra Windows usando o Cygwin.

Mas se estiver falando de C++, aí eu não sei. Talvez o @fredericopissarra?

Abraço!

Link para o comentário
Compartilhar em outros sites

É meio difícil criar um algoritmo de compactação, e existem aos montes por ai: Huffman Encoding, zlib, Lempel-Zif-Welch, etc... Mas é tremendamente mais fácil criar rotinas que leiam um bitstream. Tenho lá minhas dúvidas sobre o que o Kleber tenha feito...

Mesmo assim, tenho por política ajudar alguém que também ajuda os outros... Se o algoritmo é milagroso ou inovador, quero vê-lo antes... Curiosidade profissional.

Link para o comentário
Compartilhar em outros sites

  • 2 semanas depois...
Em 25/06/2020 em 21:42, fredericopissarra disse:

É meio difícil criar um algoritmo de compactação, e existem aos montes por ai: Huffman Encoding, zlib, Lempel-Zif-Welch, etc... Mas é tremendamente mais fácil criar rotinas que leiam um bitstream. Tenho lá minhas dúvidas sobre o que o Kleber tenha feito...

Mesmo assim, tenho por política ajudar alguém que também ajuda os outros... Se o algoritmo é milagroso ou inovador, quero vê-lo antes... Curiosidade profissional.

  Eu acho que esses algoritmos que você falou são ótimos com texto, porém o meu compactaria qualquer tipo de arquivo, talvez até vídeos e áudios, não sei como são os bits desses arquivos, mas se tiver 1 e 0 agrupados meu compactador compacta (por exemplo(111 00 1111 000 11 00), só não compacta se tiver mais bits isolados do que agrupados (por exemplo: 010101010101).

   Não é milagroso, nem inovador... mas gostaria de termina-lo.

Link para o comentário
Compartilhar em outros sites

Em 25/06/2020 em 11:18, Fernando Mercês disse:

Tem vários caminhos. O primeiro que me vem à mente é criar um buffer e usar a fread() para ler. Usando fopen, fread, fwrite, etc deixará seu programa portável, mas se a intensão é trabalhar em Linux e seus amigos somente, pode usar open(), read(), write() etc.

Na aula 18 do curso Programação Moderna em C eu falo sobre como ler os bytes de um arquivo PE (mas pode ser qualquer outro, claro):

Mas I/O é custoso. Talvez seja interessante você usar funções que leiam o arquivo inteiro para a memória e depois ler de lá. Neste caso eu não sei se tem algo portável, mas na libpe por exemplo, o @jweyrich optou por usar mmap() e a gente compila pra Windows usando o Cygwin.

Mas se estiver falando de C++, aí eu não sei. Talvez o @fredericopissarra?

Abraço!

Muito obrigado, muito boa sua aula, foi de grande valia, com isso consigo ler e escrever, porém estou com uma dificuldade: preciso tratar os bits de entrada, estou fazendo um teste só com um byte do buffer, leio o buffer na posição 100 e transformo para binário:

    for (aux = 7; aux >= 0; aux--)
    {
        if (buffer[100] % 2 == 0)
            bin[aux] = 0;
        else
            bin[aux] = 1;
        buffer[100] = buffer[100] / 2;
    }

Nesse exemplo de conversor que eu peguei na internet a cada volta no loop é gerado 1 bit do byte, o problema é que sai em inteiro e eu precisava do número em uma String para trata-lo, tentei to_String, itoa, mas nenhum deles mostra o valor correto na tela, o único que mostra o valor correto na tela é inteiro.

 

Ah muito obrigado pela ajuda!

Link para o comentário
Compartilhar em outros sites

Gente, só um alerta pra gente se ater à parte técnica da discussão (isto é, quem quiser postar) pois é muito fácil sair do controle e começar o ataque pessoal e aí entra aquele processo de apagar mensagens, blá, blá, blá. Evitem por favor. ?

@Kleber Augusto Wilcke pelo que entendi o bin é um array de int. Bom, no meu sistema aqui não tem a itoa(). Acho que não é padrão essa função. Mas de qualquer forma, os caracteres em ASCII equivalentes aos números começam em 0x30 (que é o '0'). O 0x31 é o '1' e assim vai até 9. Sendo assim, se você somar 0x30 ao int, mas fazendo um cast pra char antes pra caber na string (que é um array de char), é uma forma. Tipo, o código abaixo imprime "01010101":

#include <stdio.h>

int main(void) {
	int bin[8] = { 0, 1, 0, 1, 0, 1, 0, 1 };
	char s[9] = {0};

	for (int i=0; i<8; i++)
		s[i] = (char) bin[i] + 0x30;

	puts(s);
	return 0;
}

Mas o ideal seria escrever uma função tipo a atoi(), que tivesse checagem de erros, etc.

Link para o comentário
Compartilhar em outros sites

14 minutos atrás, Fernando Mercês disse:

Gente, só um alerta pra gente se ater à parte técnica da discussão (isto é, quem quiser postar) pois é muito fácil sair do controle e começar o ataque pessoal e aí entra aquele processo de apagar mensagens, blá, blá, blá. Evitem por favor. ?

@Kleber Augusto Wilcke pelo que entendi o bin é um array de int. Bom, no meu sistema aqui não tem a itoa(). Acho que não é padrão essa função. Mas de qualquer forma, os caracteres em ASCII equivalentes aos números começam em 0x30 (que é o '0'). O 0x31 é o '1' e assim vai até 9. Sendo assim, se você somar 0x30 ao int, mas fazendo um cast pra char antes pra caber na string (que é um array de char), é uma forma. Tipo, o código abaixo imprime "01010101":


#include <stdio.h>

int main(void) {
	int bin[8] = { 0, 1, 0, 1, 0, 1, 0, 1 };
	char s[9] = {0};

	for (int i=0; i<8; i++)
		s[i] = (char) bin[i] + 0x30;

	puts(s);
	return 0;
}

Mas o ideal seria escrever uma função tipo a atoi(), que tivesse checagem de erros, etc.

Muito obrigado, cheguei nessa solução:

inteiro = bin[7] + bin[6] * 2 + bin[5] * 4 + bin[4] * 8 + bin[3] * 16 + bin[2] * 32 + bin[1] * 64 + bin[0] * 128;
    while (inteiro > 0) {
        binario = to_string(inteiro % 2)+binario;
        inteiro /= 2;     
    }
    printf_s("%s", binario.c_str());//Binário na tela

 

Deu certo, obrigado a todos, desculpem qualquer coisa!

Link para o comentário
Compartilhar em outros sites

#include <stdlib.h>
#include <limits.h>

/* Troque MASK por 1 se quiser a ordem LSB para MSB. */
#define MASK ( 1 << CHAR_BITS - 1 )

  /* Monta string com os bits de 'byte', no buffer apontado por 'ptr'
   O buffer deve ter CHAR_BITS ou mais chars... 

  Exemplo de chamada:

    char s[CHAR_BITS+1];

    bin2str( 0x55, s );
    printf( "%s\n", s );
*/
void bin2str( unsigned char byte, char *ptr )
{
  // Um 'char' pode ter mais que 8 bits (portabilidade)!
  size_t count = CHAR_BITS;

  while ( count-- )
  {
    *ptr++ = !!( byte & MASK ) + '0';
    byte >>= 1;
  }
  *ptr = 0;  // marca fim da string.
}

 

Link para o comentário
Compartilhar em outros sites

PS: Huffman Encoding, LZW e DEFLATE (zlib) não são algoritmos para texto, mas para blocos binários. Os dois primeiros são usados em quase todos os utilitários de compressão existentes. Artigo sobre Huffman Encoding, que escrevi em janeiro de 2016, usando um texto como exemplo (mas pode ser um bloco binário): https://is.gd/1CUorF

Link para o comentário
Compartilhar em outros sites

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

  • Quem Está Navegando   0 membros estão online

    • Nenhum usuário registrado visualizando esta página.
×
×
  • Criar Novo...