Jump to content
Sign in to follow this  
Kleber Augusto Wilcke

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

 Read less than a minute

Recommended Posts

 Read less than a minute

  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.

Share this post


Link to post
Share on other sites
 Read less than a minute

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!

Share this post


Link to post
Share on other sites
Posted (edited)
 Read less than a minute

É 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.

Edited by fredericopissarra

Share this post


Link to post
Share on other sites
 Read less than a minute
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.

Share this post


Link to post
Share on other sites
 Read 1 minute
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!

Share this post


Link to post
Share on other sites
 Read less than a minute

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.

Share this post


Link to post
Share on other sites
 Read less than a minute
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!

Share this post


Link to post
Share on other sites
 Read less than a minute
#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.
}

 

Edited by fredericopissarra

Share this post


Link to post
Share on other sites
 Read less than a minute

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

  • Curtir 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...