From 2b6a0205dc2713b6e2a1057325b5dea99bf1e938 Mon Sep 17 00:00:00 2001 From: Ivan Leichenko Date: Sat, 18 Jan 2025 19:11:07 +0100 Subject: [PATCH] 2 v 1 sk1 --- sk1/compressor.c | 147 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 107 insertions(+), 40 deletions(-) diff --git a/sk1/compressor.c b/sk1/compressor.c index ece92d1..973dd58 100644 --- a/sk1/compressor.c +++ b/sk1/compressor.c @@ -353,20 +353,28 @@ LZ77Token read_token(FILE *file) { LZ77Token token; unsigned short offset_length; - fread(&offset_length, sizeof(unsigned short), 1, file); + if (fread(&offset_length, sizeof(unsigned short), 1, file) != 1) + { + token.offset = 0; + token.length = 0; + token.next_char = 0; + return token; + } token.offset = offset_length >> 4; token.length = offset_length & 0xF; - fread(&token.next_char, sizeof(char), 1, file); + if (fread(&token.next_char, sizeof(char), 1, file) != 1) + { + token.next_char = 0; + } return token; } -int compress_1(const char* input_file_name, const char* output_file_name) -{ +int compress_1(const char* input_file_name, const char* output_file_name) { FILE *input_file = fopen(input_file_name, "rb"); FILE *output_file = fopen(output_file_name, "wb"); - if (!input_file || !output_file) - { + if (!input_file || !output_file) { + perror("Ошибка открытия файла"); return -1; } @@ -374,52 +382,60 @@ int compress_1(const char* input_file_name, const char* output_file_name) long file_size = ftell(input_file); fseek(input_file, 0, SEEK_SET); - if (file_size > 10 * 1024 * 1024) - { + if (file_size > 10 * 1024 * 1024) { + fprintf(stderr, "Файл слишком большой (больше 10 МБ)\n"); return -1; } char *data = (char*)malloc(file_size); + if (!data) { + perror("Ошибка выделения памяти"); + fclose(input_file); + fclose(output_file); + return -1; + } + fread(data, 1, file_size, input_file); int pos = 0; - while (pos < file_size) - { + while (pos < file_size) { LZ77Token token = {0, 0, data[pos]}; int max_length = 0; int max_offset = 0; int start = (pos - WINDOW_SIZE) > 0 ? (pos - WINDOW_SIZE) : 0; - for (int i = start; i < pos; i++) - { + for (int i = start; i < pos; i++) { int length = 0; - while (length < LOOKAHEAD_BUFFER_SIZE && pos + length < file_size && data[i + length] == data[pos + length]) - { + while (length < LOOKAHEAD_BUFFER_SIZE && pos + length < file_size && data[i + length] == data[pos + length]) { length++; } - if (length > max_length) - { + if (length > max_length) { max_length = length; max_offset = pos - i; } } - if (max_length > 1) - { + if (max_length > 1) { token.offset = max_offset; token.length = max_length; token.next_char = data[pos + max_length]; pos += max_length + 1; - } - else - { + } else { pos++; } + // Записываем токен write_token(output_file, token); } + fseek(input_file, 0, SEEK_END); + long sizeIN = ftell(input_file); + fseek(input_file, 0, SEEK_SET); + + // Записываем реальный размер входного файла для декомпрессии + fwrite(&sizeIN, sizeof(sizeIN), 1, output_file); + fseek(output_file, 0, SEEK_END); int sizeOUT = ftell(output_file); fseek(output_file, 0, SEEK_SET); @@ -431,37 +447,88 @@ int compress_1(const char* input_file_name, const char* output_file_name) return sizeOUT; } -int decompress_1(const char* input_file_name, const char* output_file_name) -{ + + + + + + +int decompress_1(const char* input_file_name, const char* output_file_name) { FILE *input_file = fopen(input_file_name, "rb"); FILE *output_file = fopen(output_file_name, "wb"); - if (!input_file || !output_file) - { + if (!input_file || !output_file) { + perror("Ошибка открытия файла"); return -1; } char *window = (char*)malloc(WINDOW_SIZE); + if (!window) { + perror("Ошибка выделения памяти"); + fclose(input_file); + fclose(output_file); + return -1; + } + + memset(window, 0, WINDOW_SIZE); + + fseek(input_file, -sizeof(long), SEEK_END); + long original_size; + fread(&original_size, sizeof(long), 1, input_file); + + int byte_written = 0; + + fseek(input_file, 0, SEEK_SET); + int window_pos = 0; - while (!feof(input_file)) - { - LZ77Token token = read_token(input_file); + while (1) { + unsigned short offset_length; + char next_char; - if (token.length > 0) - { - int start = window_pos - token.offset; - for (int i = 0; i < token.length; i++) - { - char c = window[(start + i) % WINDOW_SIZE]; - fputc(c, output_file); - window[window_pos % WINDOW_SIZE] = c; - window_pos++; + // Читаем offset и length (2 байта) + if (fread(&offset_length, sizeof(unsigned short), 1, input_file) != 1) { + break; // Конец файла + } + + // Читаем следующий символ (1 байт) + if (fread(&next_char, sizeof(char), 1, input_file) != 1) { + break; // Конец файла + } + + // Распаковываем offset и length + int offset = offset_length >> 4; // Старшие 12 бит + int length = offset_length & 0xF; // Младшие 4 бита + + // Обрабатываем токен + if (length > 0) { + int start = window_pos - offset; + for (int i = 0; i < length; i++) { + //доп проверка на лишние символы + if (byte_written < original_size) { + char c = window[(start + i) % WINDOW_SIZE]; + fputc(c, output_file); + byte_written++; + // Обновляем окно + window[window_pos % WINDOW_SIZE] = c; + window_pos++; + } } } - fputc(token.next_char, output_file); - window[window_pos % WINDOW_SIZE] = token.next_char; - window_pos++; + + // Записываем следующий символ только если не достигнут конец файла + if (byte_written < original_size) { + fputc(next_char, output_file); + byte_written++; + + // Обновляем окно + window[window_pos % WINDOW_SIZE] = next_char; + window_pos++; + } + else + { + break; + } } fseek(output_file, 0, SEEK_END);