Обновить 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