1 v 1 sk1

This commit is contained in:
Ivan Leichenko 2025-01-18 13:15:16 +01:00
parent 46a15ce65a
commit 1f566ebe0f
2 changed files with 68 additions and 19 deletions

View File

@ -3,6 +3,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
#include <unistd.h>
#define WINDOW_SIZE 4096 // Размер скользящего окна #define WINDOW_SIZE 4096 // Размер скользящего окна
#define LOOKAHEAD_BUFFER_SIZE 15 // Размер буфера предпросмотра #define LOOKAHEAD_BUFFER_SIZE 15 // Размер буфера предпросмотра
@ -150,11 +151,15 @@ void free_tree(Node* root)
int compress_2(const char* input_file_name, const char* output_file_name) int compress_2(const char* input_file_name, const char* output_file_name)
{ {
FILE* input = fopen(input_file_name, "rb"); FILE* input = fopen(input_file_name, "rb");
if (!input) return -1; if (!input)
{
return -1;
}
int freq[MAX_TREE_NODES] = {0}; int freq[MAX_TREE_NODES] = {0};
unsigned char buffer; unsigned char buffer;
// Читаем файл и подсчитываем частоты символов
while (fread(&buffer, 1, 1, input)) while (fread(&buffer, 1, 1, input))
{ {
freq[buffer]++; freq[buffer]++;
@ -175,7 +180,9 @@ int compress_2(const char* input_file_name, const char* output_file_name)
char code[MAX_TREE_NODES]; char code[MAX_TREE_NODES];
build_codes(heap->nodes[0], code, 0, codes); build_codes(heap->nodes[0], code, 0, codes);
// Вернемся в начало входного файла
fseek(input, 0, SEEK_SET); fseek(input, 0, SEEK_SET);
FILE* output = fopen(output_file_name, "wb"); FILE* output = fopen(output_file_name, "wb");
if (!output) if (!output)
{ {
@ -183,14 +190,17 @@ int compress_2(const char* input_file_name, const char* output_file_name)
return -1; return -1;
} }
// Записываем частоты символов
fwrite(freq, sizeof(freq), 1, output); fwrite(freq, sizeof(freq), 1, output);
unsigned char out_buffer = 0; unsigned char out_buffer = 0;
int bit_count = 0; int bit_count = 0;
// Записываем закодированные данные
while (fread(&buffer, 1, 1, input)) while (fread(&buffer, 1, 1, input))
{ {
char* symbol_code = codes[buffer]; char* symbol_code = codes[buffer];
for (int i = 0; symbol_code[i] != '\0'; i++) for (int i = 0; symbol_code[i] != '\0'; i++)
{ {
out_buffer <<= 1; out_buffer <<= 1;
@ -215,6 +225,13 @@ int compress_2(const char* input_file_name, const char* output_file_name)
fwrite(&out_buffer, 1, 1, output); fwrite(&out_buffer, 1, 1, output);
} }
fseek(input, 0, SEEK_END);
long sizeIN = ftell(input);
fseek(input, 0, SEEK_SET);
// Записываем реальный размер входного файла для декомпрессии
fwrite(&sizeIN, sizeof(sizeIN), 1, output);
fseek(output, 0, SEEK_END); fseek(output, 0, SEEK_END);
int sizeOUT = ftell(output); int sizeOUT = ftell(output);
fseek(output, 0, SEEK_SET); fseek(output, 0, SEEK_SET);
@ -230,7 +247,10 @@ int compress_2(const char* input_file_name, const char* output_file_name)
int decompress_2(const char* input_file_name, const char* output_file_name) int decompress_2(const char* input_file_name, const char* output_file_name)
{ {
FILE* input = fopen(input_file_name, "rb"); FILE* input = fopen(input_file_name, "rb");
if (!input) return -1; if (!input)
{
return -1;
}
int freq[MAX_TREE_NODES]; int freq[MAX_TREE_NODES];
fread(freq, sizeof(freq), 1, input); fread(freq, sizeof(freq), 1, input);
@ -250,30 +270,55 @@ int decompress_2(const char* input_file_name, const char* output_file_name)
if (!output) if (!output)
{ {
fclose(input); fclose(input);
free_tree(heap->nodes[0]);
free(heap);
return -1; return -1;
} }
Node* root = heap->nodes[0]; Node* root = heap->nodes[0];
Node* current = root; Node* current = root;
unsigned char buffer;
while (fread(&buffer, 1, 1, input)) // Перемещаемся к концу файла, чтобы прочитать оригинальный размер
fseek(input, -sizeof(long), SEEK_END);
long original_size;
fread(&original_size, sizeof(long), 1, input);
// Вернемся к началу сжатых данных
long data_end = ftell(input) - sizeof(long);
fseek(input, sizeof(freq), SEEK_SET);
long written_bytes = 0;
unsigned char buffer;
int bit_count = 0;
while (ftell(input) < data_end || (bit_count > 0 && written_bytes < original_size))
{ {
for (int i = 7; i >= 0; i--) if (bit_count == 0 && fread(&buffer, 1, 1, input) == 1)
{ {
if ((buffer >> i) & 1) bit_count = 8;
{ }
current = current->right;
} if (bit_count > 0)
else {
{ int bit = (buffer >> (bit_count - 1)) & 1;
current = current->left; bit_count--;
}
current = bit ? current->right : current->left;
if (!current->left && !current->right) if (!current->left && !current->right)
{ {
fwrite(&current->symbol, 1, 1, output); if (written_bytes < original_size)
{
fwrite(&current->symbol, 1, 1, output);
written_bytes++;
}
current = root; current = root;
// Остановимся, если записали все байты
if (written_bytes == original_size)
{
break;
}
} }
} }
} }
@ -290,6 +335,10 @@ int decompress_2(const char* input_file_name, const char* output_file_name)
return sizeOUT; return sizeOUT;
} }
// Функция для записи токена в файл в компактном формате // Функция для записи токена в файл в компактном формате
void write_token(FILE *file, LZ77Token token) void write_token(FILE *file, LZ77Token token)
{ {