-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdescompactador.c
108 lines (90 loc) · 3.1 KB
/
descompactador.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/*
*
* TAD REFERENTE AO TRABALHO DA DISCIPLINA DE ESTRUTURA DE DADOS I
* COMPACTADOR DE HUFFMAN
*
* ALUNAS: BARBARA ALENCAR DE ARAUJO PEREIRA E MARIA EDUARDA NOIA MATTOS DE AZEVEDO
*
*/
#include "descompactador.h"
#define MEGA_BYTE (1024 * 1024)
void descompactaArquivo(FILE *entrada, char *caminhoSaida) {
FILE *arquivoSaida = fopen(caminhoSaida, "wb");
if (!arquivoSaida) {
printf("Erro ao abrir o arquivo %s\n", caminhoSaida);
return;
}
// le o tamanho do bitmap
unsigned int bmSize;
if (fread(&bmSize, sizeof(unsigned int), 1, entrada) != 1) {
printf("Erro ao ler o tamanho do bitmap.\n");
fclose(arquivoSaida);
return;
}
// calcula o tamanho do bitmap em bytes
unsigned int bmSizeInBytes = (bmSize + 7) / 8;
// cria o contents do bitmap pra jogar nele depois
unsigned char *bmContents = (unsigned char *)malloc(bmSizeInBytes);
if (!bmContents) {
printf("Erro ao alocar memória para o bitmap.\n");
fclose(arquivoSaida);
return;
}
// le o conteúdo do bitmap
if (fread(bmContents, sizeof(unsigned char), bmSizeInBytes, entrada) != bmSizeInBytes) {
printf("Erro ao ler o conteúdo do bitmap.\n");
free(bmContents);
fclose(arquivoSaida);
return;
}
// inicializa o bitmap com o conteudo que foi lido
bitmap *bm = bitmapInit(bmSize);
for (unsigned int i = 0; i < bmSize; i++) {
unsigned char bit = (bmContents[i / 8] >> (7 - (i % 8))) & 0x01;
bitmapAppendLeastSignificantBit(bm, bit);
}
free(bmContents);
// le a arvore de volta do bitmap
unsigned int bitIndex = 0;
Arv *a = leArvoreCabecalho(bm, &bitIndex);
if (!a) {
printf("Erro ao ler o cabeçalho\n");
bitmapLibera(bm);
fclose(arquivoSaida);
return;
}
// le o numero de bytes originais pra nao acessar o resto
int bytes;
if (fread(&bytes, sizeof(int), 1, entrada) != 1) {
printf("Erro ao ler o número de bytes originais.\n");
bitmapLibera(bm);
fclose(arquivoSaida);
return;
}
Arv *noAtual = a;
unsigned char byte;
int bytesEscritos = 0;
unsigned char bitBuffer = 0;
// passa pelo arquivo bit a bit
while (fread(&byte, sizeof(unsigned char), 1, entrada) == 1) {
for (int bit = 7; bit >= 0; bit--) {
unsigned char mask = 1 << bit;
unsigned char bitValue = (byte & mask) >> bit;
// se escreveu todos os bytes, para
if (bytesEscritos == bytes)
break;
// navega na arvore com base no bit
noAtual = percorreArvore(noAtual, bitValue);
// se achou folha escreve o caractere
if (ehFolhaArvore(noAtual)) {
unsigned char c = retornaCaracterArvore(noAtual);
fwrite(&c, sizeof(unsigned char), 1, arquivoSaida);
noAtual = a; // retorna pro inicio da arvore para o próximo caractere
bytesEscritos++;
}
}
}
bitmapLibera(bm);
liberaArvore(a);
fclose(arquivoSaida);
}