2 v 1 sk1

This commit is contained in:
Ivan Leichenko 2025-01-18 19:11:07 +01:00
parent 1f566ebe0f
commit 2b6a0205dc

View File

@ -353,20 +353,28 @@ LZ77Token read_token(FILE *file)
{ {
LZ77Token token; LZ77Token token;
unsigned short offset_length; 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.offset = offset_length >> 4;
token.length = offset_length & 0xF; 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; 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 *input_file = fopen(input_file_name, "rb");
FILE *output_file = fopen(output_file_name, "wb"); FILE *output_file = fopen(output_file_name, "wb");
if (!input_file || !output_file) if (!input_file || !output_file) {
{ perror("Ошибка открытия файла");
return -1; 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); long file_size = ftell(input_file);
fseek(input_file, 0, SEEK_SET); fseek(input_file, 0, SEEK_SET);
if (file_size > 10 * 1024 * 1024) if (file_size > 10 * 1024 * 1024) {
{ fprintf(stderr, "Файл слишком большой (больше 10 МБ)\n");
return -1; return -1;
} }
char *data = (char*)malloc(file_size); char *data = (char*)malloc(file_size);
if (!data) {
perror("Ошибка выделения памяти");
fclose(input_file);
fclose(output_file);
return -1;
}
fread(data, 1, file_size, input_file); fread(data, 1, file_size, input_file);
int pos = 0; int pos = 0;
while (pos < file_size) while (pos < file_size) {
{
LZ77Token token = {0, 0, data[pos]}; LZ77Token token = {0, 0, data[pos]};
int max_length = 0; int max_length = 0;
int max_offset = 0; int max_offset = 0;
int start = (pos - WINDOW_SIZE) > 0 ? (pos - WINDOW_SIZE) : 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; 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++; length++;
} }
if (length > max_length) if (length > max_length) {
{
max_length = length; max_length = length;
max_offset = pos - i; max_offset = pos - i;
} }
} }
if (max_length > 1) if (max_length > 1) {
{
token.offset = max_offset; token.offset = max_offset;
token.length = max_length; token.length = max_length;
token.next_char = data[pos + max_length]; token.next_char = data[pos + max_length];
pos += max_length + 1; pos += max_length + 1;
} } else {
else
{
pos++; pos++;
} }
// Записываем токен
write_token(output_file, token); 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); fseek(output_file, 0, SEEK_END);
int sizeOUT = ftell(output_file); int sizeOUT = ftell(output_file);
fseek(output_file, 0, SEEK_SET); fseek(output_file, 0, SEEK_SET);
@ -431,38 +447,89 @@ int compress_1(const char* input_file_name, const char* output_file_name)
return sizeOUT; 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 *input_file = fopen(input_file_name, "rb");
FILE *output_file = fopen(output_file_name, "wb"); FILE *output_file = fopen(output_file_name, "wb");
if (!input_file || !output_file) if (!input_file || !output_file) {
{ perror("Ошибка открытия файла");
return -1; return -1;
} }
char *window = (char*)malloc(WINDOW_SIZE); 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; int window_pos = 0;
while (!feof(input_file)) while (1) {
{ unsigned short offset_length;
LZ77Token token = read_token(input_file); char next_char;
if (token.length > 0) // Читаем offset и length (2 байта)
{ if (fread(&offset_length, sizeof(unsigned short), 1, input_file) != 1) {
int start = window_pos - token.offset; break; // Конец файла
for (int i = 0; i < token.length; i++) }
{
// Читаем следующий символ (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]; char c = window[(start + i) % WINDOW_SIZE];
fputc(c, output_file); fputc(c, output_file);
byte_written++;
// Обновляем окно
window[window_pos % WINDOW_SIZE] = c; window[window_pos % WINDOW_SIZE] = c;
window_pos++; window_pos++;
} }
} }
fputc(token.next_char, output_file); }
window[window_pos % WINDOW_SIZE] = token.next_char;
// Записываем следующий символ только если не достигнут конец файла
if (byte_written < original_size) {
fputc(next_char, output_file);
byte_written++;
// Обновляем окно
window[window_pos % WINDOW_SIZE] = next_char;
window_pos++; window_pos++;
} }
else
{
break;
}
}
fseek(output_file, 0, SEEK_END); fseek(output_file, 0, SEEK_END);
int sizeOUT = ftell(output_file); int sizeOUT = ftell(output_file);