Jump to content

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


Guest Kleber Augusto Wilcke

Recommended Posts

Guest Kleber Augusto Wilcke
Posted

  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.

  • Administrators
Posted

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!

Posted

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

  • 2 weeks later...
Guest Kleber Augusto Wilcke
Posted
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.

Guest Kleber Augusto Wilcke
Posted

Você quer vê-lo antes, a minha ajuda vai ser distribuir o programa, não entragar o ouro pro bandido, demorei 5 anos pra conseguir fazer um algoritmo funcional!

Guest Kleber Augusto Wilcke
Posted
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!

Guest Kleber Augusto Wilcke
Posted

E mesmo em inteiro eu não consegui concatenar os números para guardar em uma variável!

Guest Kleber Augusto Wilcke
Posted
7 horas atrás, fredericopissarra disse:

Boa sorte...

Obrigado, se eu conseguir terminar eu te mando uma cópia pra você falar mal...rsrsrs

  • Administrators
Posted

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.

Guest Kleber Augusto Wilcke
Posted
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!

Posted
#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.
}

 

Posted

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

Archived

This topic is now archived and is closed to further replies.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...