2 v 1 sk1
This commit is contained in:
parent
1f566ebe0f
commit
2b6a0205dc
137
sk1/compressor.c
137
sk1/compressor.c
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user