diff --git a/sk1/compressor.c b/sk1/compressor.c index 98dd1b6..65328c6 100644 --- a/sk1/compressor.c +++ b/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; + } + + 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_2(const char* input_file_name, const char* output_file_name){ - return 0; + +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); }