Обновить 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; | ||||
|     } | ||||
| 
 | ||||
|     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); | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user