Обновить sk1/compressor.c
This commit is contained in:
parent
183e166d8b
commit
33192ea354
170
sk1/compressor.c
170
sk1/compressor.c
@ -16,6 +16,12 @@ typedef struct Node {
|
||||
struct Node *left, *right;
|
||||
} Node;
|
||||
|
||||
typedef struct LZ77{
|
||||
int posun;
|
||||
int dlzka;
|
||||
char dalsi_znak;
|
||||
} LZ77;
|
||||
|
||||
// Функция для создания нового узла
|
||||
Node* create_node(int symbol, unsigned int frequency) {
|
||||
Node* node = (Node*)malloc(sizeof(Node));
|
||||
@ -89,7 +95,7 @@ void free_huffman_tree(Node* root) {
|
||||
}
|
||||
|
||||
// Функция сжатия данных с использованием алгоритма Хаффмана
|
||||
int compress_1(const char* input_file, const char* output_file) {
|
||||
int compress_2(const char* input_file, const char* output_file) {
|
||||
FILE* input = fopen(input_file, "rb");
|
||||
FILE* output = fopen(output_file, "wb");
|
||||
if (!input || !output) return -1;
|
||||
@ -160,7 +166,7 @@ int compress_1(const char* input_file, const char* output_file) {
|
||||
}
|
||||
|
||||
// Функция декомпрессии данных с использованием алгоритма Хаффмана
|
||||
int decompress_1(const char* input_file, const char* output_file) {
|
||||
int decompress_2(const char* input_file, const char* output_file) {
|
||||
FILE* input = fopen(input_file, "rb");
|
||||
FILE* output = fopen(output_file, "wb");
|
||||
if (!input || !output) return -1;
|
||||
@ -198,10 +204,162 @@ int decompress_1(const char* input_file, const char* output_file) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int compress_2(const char* input_file_name, const char* output_file_name){
|
||||
return 0;
|
||||
|
||||
int compress_1(const char *input_file, const char *output_file) {
|
||||
FILE *source = fopen(input_file, "rb");
|
||||
if (source == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int decompress_2(const char* input_file_name, const char* output_file_name){
|
||||
return 0;
|
||||
FILE *destination = fopen(output_file, "wb");
|
||||
if (destination == NULL) {
|
||||
fclose(source);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fseek(source, 0, SEEK_END);
|
||||
long file_size = ftell(source);
|
||||
if (file_size > 10 * 1024 * 1024) {
|
||||
fclose(source);
|
||||
fclose(destination);
|
||||
return -1;
|
||||
}
|
||||
fseek(source, 0, SEEK_SET); // Возврат в начало файла для чтения
|
||||
|
||||
char *input_data = malloc(file_size);
|
||||
if (input_data == NULL) {
|
||||
fclose(source);
|
||||
fclose(destination);
|
||||
return -1;
|
||||
}
|
||||
fread(input_data, 1, file_size, source);
|
||||
|
||||
int index = 0;
|
||||
while (index < file_size) {
|
||||
LZ77 element = {0, 0, input_data[index]}; // Инициализация элемента с текущим символом
|
||||
int best_length = 0, best_offset = 0;
|
||||
int start_idx;
|
||||
|
||||
if ((index - WINDOW_CAPACITY) > 0) {
|
||||
start_idx = index - WINDOW_CAPACITY;
|
||||
} else {
|
||||
start_idx = 0;
|
||||
} // Поиск начала окна
|
||||
|
||||
// Поиск наилучшего совпадения в окне
|
||||
for (int i = start_idx; i < index; i++) {
|
||||
int match_length = 0;
|
||||
while (match_length < MAX_MATCH_LENGTH && index + match_length < file_size &&
|
||||
input_data[i + match_length] == input_data[index + match_length]) {
|
||||
match_length++;
|
||||
}
|
||||
|
||||
if (match_length > best_length) {
|
||||
best_length = match_length;
|
||||
best_offset = index - i;
|
||||
}
|
||||
|
||||
if (match_length == MAX_MATCH_LENGTH) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Если найдено совпадение записываем его в элемент иначе сохраняем символ
|
||||
if (best_length > 1) {
|
||||
element.posun = best_offset;
|
||||
element.dlzka = best_length;
|
||||
element.dalsi_znak = input_data[index + best_length];
|
||||
index += best_length + 1;
|
||||
} else {
|
||||
element.posun = 0;
|
||||
element.dlzka = 0;
|
||||
element.dalsi_znak = input_data[index];
|
||||
index++;
|
||||
}
|
||||
|
||||
|
||||
unsigned short combined = (element.posun << 4) | (element.dlzka & 0xF); // Объединение posun и dlzka в одно значение
|
||||
fwrite(&combined, sizeof(unsigned short), 1, destination);
|
||||
fwrite(&element.dalsi_znak, sizeof(char), 1, destination);
|
||||
}
|
||||
|
||||
fwrite(&file_size, sizeof(file_size), 1, destination);
|
||||
free(input_data);
|
||||
fclose(source);
|
||||
fclose(destination);
|
||||
return ftell(destination);
|
||||
}
|
||||
|
||||
|
||||
int decompress_1(const char *input_file, const char *output_file) {
|
||||
FILE *source = fopen(input_file, "rb");
|
||||
if (source == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE *destination = fopen(output_file, "wb");
|
||||
if (destination == NULL) {
|
||||
fclose(source);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *buffer = malloc(WINDOW_CAPACITY);
|
||||
if (buffer == NULL) {
|
||||
fclose(source);
|
||||
fclose(destination);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(buffer, 0, WINDOW_CAPACITY);
|
||||
// Переход к концу файла для чтения размера исходного файла
|
||||
fseek(source, -sizeof(long), SEEK_END);
|
||||
long original_size;
|
||||
if (fread(&original_size, sizeof(long), 1, source) != 1) {
|
||||
free(buffer);
|
||||
fclose(source);
|
||||
fclose(destination);
|
||||
return -1;
|
||||
}
|
||||
// Возврат в начало файла для распаковки
|
||||
fseek(source, 0, SEEK_SET);
|
||||
|
||||
int written_bytes = 0, buffer_position = 0;
|
||||
while (written_bytes < original_size) {
|
||||
unsigned short combined;
|
||||
char dalsi_znak;
|
||||
if (fread(&combined, sizeof(unsigned short), 1, source) != 1) {
|
||||
break;
|
||||
}
|
||||
if (fread(&dalsi_znak, sizeof(char), 1, source) != 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
int posun = combined >> 4;
|
||||
int dlzka = combined & 0xF;
|
||||
|
||||
// Восстановление данных из совпадений в буфере
|
||||
if (dlzka > 0) {
|
||||
int start_idx = buffer_position - posun;
|
||||
for (int i = 0; i < dlzka; i++) {
|
||||
char current = buffer[(start_idx + i) % WINDOW_CAPACITY];
|
||||
fputc(current, destination);
|
||||
buffer[buffer_position % WINDOW_CAPACITY] = current;
|
||||
buffer_position++;
|
||||
written_bytes++;
|
||||
}
|
||||
}
|
||||
|
||||
// Запись следующего символа в файл
|
||||
if (written_bytes < original_size) {
|
||||
fputc(dalsi_znak, destination);
|
||||
buffer[buffer_position % WINDOW_CAPACITY] = dalsi_znak;
|
||||
buffer_position++;
|
||||
written_bytes++;
|
||||
}
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
fclose(source);
|
||||
fclose(destination);
|
||||
return ftell(destination);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user