РефератыИнформатика, программированиеРаРазработка программы сжатия и восстановления файлов с помощью фиксированного блочного кода постоянного смещения

Разработка программы сжатия и восстановления файлов с помощью фиксированного блочного кода постоянного смещения

Содержание


Краткое описание работы программы


Код программы


Результаты тестирования приложения


Краткое описание работы программы

Используемые компоненты среды
Delphi
:


1. SaveDialog, OpenDialog. Копомненты необходимые для чтения и сохранения файлов, а так же получения названия файла и его пути до него.


2. Button - компонент кнопка.


3. ListBox - компонент, состоящий из строк, хранит кодовые слова.


4. ProgressBar - компонент, необходимый для отслеживания этапов выполнения программы.


5. Label - компонент для вывода строковых данных.


Краткое описание работы приложения:


1. При нажатии кнопки Button1 “Считать для сжатия” происходит получение имени считываемого файла и пути до него. Измеряется размер файла (функция FileSize). Полностью очищаются Label.


2. При нажатии кнопки Button2 “Проверить” происходит обнуление всех необходимых для работы переменных. Запускается процесс считывания (по-байтово) и анализа сжимаемого файла, в результате которого высчитывается средняя длинна кодового слова. Она необходима для определения возможности сжатия. В зависимости от полученного результата выводится сообщение о том, что файл можно сжимать, в противном случае, что нельзя. Так же формируется массив частот повторений символов в файле, необходимый для соотнесения кодовых слов и символов в файле.


3. При нажатии Button3 “Сжать” происходит побайтовое считывание сжимаемого файла с помощью команды BlockRead. Далее происходит соотнесение считанного байта кодовому слову. Алгоритм соотнесения основан на частоте появлений символов в файле. Чем чаще данный символ встречается в файле, тем меньшей длинны ему присваивается кодовое слово. Запись нового файла производится с помощью команды BlockWriteтак же по-байтово. Новому файлу присваивается новое расширение. Когда файл полностью считан, выполняется проверка на наличие оставшихся битов. Если таковые имеются, то пустое пространство забивается нулями до тех пор, пока количество битов не будет равно 8.


4. При нажатии Button4 “Считать для восстановления” происходит получение имени сжатого файла, пути до него.


5. При нажатии Button5 “Восстановить" происходит побайтового считывание файла. Алгоритм разжатия состоит из двух этапов. На первом этапе происходит считывание файла блоками размером в 1 байт. Производится запись считанных байтов в специальную переменную. Когда длина переменной составляет 16 символов или более, начинается анализ считанной информации. Производится проверка на соответствие кодовым словам и последующая запись полученных значений в новый файл. На втором этапе производится проверка на остаток и удаление лишних данных (случай, когда было выполнено дополнение нулями при сжатии).


Код
программы
:


unit Unit1;


interface


uses


Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,


Dialogs, StdCtrls, ComCtrls;


type


TForm1 = class (TForm)


ListBox1: TListBox;


OpenDialog1: TOpenDialog;


SaveDialog1: TSaveDialog;


Button1: TButton;


Button2: TButton;


Button3: TButton;


Label1: TLabel;


ProgressBar1: TProgressBar;


Button4: TButton;


Button5: TButton;


Label3: TLabel;


Label4: TLabel;


Label2: TLabel;


Label5: TLabel;


Label6: TLabel;


Label7: TLabel;


Label8: TLabel;


SaveDialog2: TSaveDialog;


OpenDialog2: TOpenDialog;


procedure Button1Click (Sender: TObject);


procedure FormCreate (Sender: TObject);


procedure Button2Click (Sender: TObject);


procedure Button3Click (Sender: TObject);


procedure Button4Click (Sender: TObject);


procedure Button5Click (Sender: TObject);


private


{ Private declarations }


public


{ Public declarations }


end;


var


Form1: TForm1;


f,f1,f2,f3: file;


buff: byte;


conR,conW: string;


a: array [0.255] of real; // массив вероятностей


word: array [0.255] of string; // массив кодовых слов


l: array [0.255] ofbyte; // массив длин кодовых слов


e: array [0.255] ofreal; // массив номеров элементов


inf: array [0.255] of integer; // массив служебной информации


i,j,k,size,prog,buff1,buff3,check,dop: integer;


sl,sum,sort,sort1,buff2: real;


implementation


{$R *.dfm}


procedure TForm1.Button1Click (Sender: TObject);


begin


if OpenDialog1.Execute then


AssignFile (f,OpenDialog1.FileName); // считываем имя файла и путь до него


Reset (f,1); // открываем файл для чтения и изменения


size: =FileSize (f); // измеряем размер файла


Label4.Caption: =IntToStr (size) + ' байт';


// выводим размер файла в Label4


Label2.Caption: ='';


Label6.Caption: ='';


Label8.Caption: ='';


end;


procedure TForm1.Button2Click (Sender: TObject);


begin


ProgressBar1.Position: =0; // обнуляем ProgressBar


prog: =0; // обнуляем счетчик для Progress Bar


sl: =0; // обнуляем переменную средней длинны


sum: =0; // обнуляем счетчик повторений символов


sort: =0; // обнуляем переменные для сортировки массива номеров элементов


sort1: =0;


buff: =0;


for i: =0 to 255 do


begin


e [i]: =i; // производим обнуление элементов массивов кодовых слов, длин кодовых слов, вероятностей и номеров элементов.


l [i]: =0;


word [i]: ='';


a [i]: =0;


end;


whilenotEOF (f) do // считываем файл до его окончания


begin


BlockRead (f,buff,1); // считываем блоки в 1 байт


a [buff]: =a [buff] +1; // записываем этот байт в массив


prog: =prog+1;


ProgressBar1.Position: =round ( (prog/size) *100);


end;


for i: =0 to 255 do


begin


word [i]: =ListBox1. Items.Strings [i]; // записываем кодовые слова из ListBox1 в массив кодовых слов


ifa [i] <>0 then // проверяем наличие байта в массиве


begin


sum: = sum+a [i]; // считаем количество повторений данного байта


end;


end;


CloseFile (f); // закрываем файл после чтения


for i: =0 to 255 do


begin


for j: =0 to 254 do


begin


if (a [j] < a [j+1]) then


begin


sort: =a [j]; // производим сортировку массива номеров элементов


sort1: =e [j];


a [j]: =a [j+1];


a [j+1]: =sort;


e [j]: =e [j+1];


e [j+1]: =sort1;


end;


end;


end;


for k: =0 to 255 do


begin


ifa [k] <>0 then // проверяем наличие элементов в массиве


begin


a [k]: =a [k] /sum; // считаем у появления символа


l [k]: =length (word [k]); // высчитываем длину кодовых слов


sl: =sl+l [k] *a [k]; // получаем значение средней длинны


end;


end;


Label2.Caption: =FloatToStr (sl); // выводим значение средней длины


ifsl< 8 then // проверяем значение средней длины


begin


Button3.Enabled: =true; // активируем кнопку “Сжать”


showmessage ('Сжатие возможно');


end;


if sl > 8 then


begin


showmessage ('Сжатие невозможно');


end;


end;


procedure TForm1.Button3Click (Sender: TObject);


begin


SaveDialog1.FileName: =OpenDialog1.FileName+'.gop';


// задаем новое расширение для сжатого файла


SaveDialog1.DefaultExt: ='gop';


if SaveDialog1.Execute then


begin


AssignFile (f1, SaveDialog1.FileName);


Rewrite (f1,1); // открываем файл для записи


end;


buff1: =0;


i: =0;


whilei<> 256 do // записываем служебную информацию в новый файл.


begin


buff1: =StrToInt (FloatToStr (e [i]));


BlockWrite (f1,buff1,1);


Reset (f,1);


i: =i+1;


end;


buff1: =0;


seek (f1,256); // осуществляем переход на 256-ой байт в файле


ProgressBar1.Position: =0;


prog: =0;


while not EOF (f) do // считываем файл до его окончания


begin


BlockRead (f,buff,1); // считываем блоки размером 1 байт


buff1: =buff1+1;


prog: =prog+1;


for i: =0 to 255 do


begin


if buff=e [i] then // проверяем совпадения


begin


conR: =conR+word [i]; // записываем соответствующее кодовое слово


iflength (conR) >=8 then // проверяем длину переменной


begin


conW: =copy (conR,1,8); // копируем первые 8 символов


buff2: = ( (strtoint (conW [1])) *128) + ( (strtoint (conW [2])) *64) + ( (strtoint (conW [3])) *32) + ( (strtoint (conW [4])) *16) + ( (strtoint (conW [5])) *8) + ( (strtoint (conW [6])) *4) + ( (strtoint (conW [7])) *2) + (strtoint (conW [8]));


// переводим скопрированную информацию в десятичное число


buff3: =strtoint (floattostr (buff2));


BlockWrite (f1,buff3,1); // записываем результат в новый файл


Delete (conR,1,8); // удаляем первые 8 символов


end;


if (EOF (f) =true) and (conR<>'') and (length (conR) <8) then


// проверяем наличие остатка


begin


k: =0;


check: =length (conR); // вычисляем длину остатка


dop: =8-check; // вычисляем количество необходимых для заполнения битов


whilek<>dopdo // цикл дополнения нулями


begin


conR: =conR+'0'; // дописываем нули


k: =k+1;


end;


conW: =copy (conR,1,8); // копируем данные


buff2: = ( (strtoint (conW [1])) *128) + ( (strtoint (conW [2])) *64) + ( (strtoint (conW [3])) *32) + ( (strtoint (conW [4])) *16) + ( (strtoint (conW [5])) *8) + ( (strtoint (conW [6])) *4) + ( (strtoint (conW [7])) *2) + (strtoint (conW [8]));


// переводим скопированную информацию в десятичное число


buff3: =strtoint (floattostr (buff2));


BlockWrite (f1,buff3,1); // записываем полученные значения


end;


end;


end;


ProgressBar1.Position: =Round ( (prog/size) *100);


end;


Label6.Caption: =Inttostr (FileSize (f1)) + ' байт';


// выводим размер полученного файла


Label8.Caption: =IntToStr (Round (100- (FileSize (f1) *100/size))) + ' %';


// считаем процент сжатия файла


ShowMessage ('Файл успешно сжат');


CloseFile (f); // закрываем файлы


CloseFile (f1);


conR: =''; // обнуляем переменные


conW: ='';


Button3.Enabled: =false;


end;


procedure TForm1.Button4Click (Sender: TObject);


begin


if OpenDialog2.Execute then


AssignFile (f2,OpenDialog2.FileName); // считываем имя файла и путь до него

p>

Reset (f2,1); // открываем файл для чтения и записи


size: =FileSize (f2); // запоминаем размер файла


Label4.Caption: =IntToStr (size) + ' байт';


Label2.Caption: ='';


Label6.Caption: ='';


Label8.Caption: ='';


Button5.Enabled: =true;


for i: =0 to 255 do


begin


BlockRead (f2,buff,1);


inf [i]: =buff; // задаем соответствие по служебной информации


word [i]: =ListBox1. Items.Strings [i]; // считываем массив кодовых слов


end;


end;


functionIntToBin (n: Integer): String; // перевод из десятичного значения в двоичное


var


m: integer;


begin


Result: ='';


while n<>0 do


begin


if n and 1=0 then Result: ='0'+Result else Result: ='1'+Result;


n: =n shr 1;


end;


if length (result) <8 then


begin


for m: =1 to 8-length (result) do result: ='0'+result;


end;


end;


procedure TForm1.Button5Click (Sender: TObject);


begin


if SaveDialog2.Execute then


begin


ProgressBar1.Position: =0;


prog: =0;


AssignFile (f3, SaveDialog2.FileName); // считываем имя файла и путь до него


ReWrite (f3,1); // открываем файл для записи


conR: =''; // обнуляем рабочие переменные


conW: ='';


seek (f2,256); // переходим на 256-ой байт


form1.Refresh;


WhilenotEOF (f2) do // считываем файл до его окончания


begin


iflength (conR) <16 then // проверяем длину рабочей переменной


begin


BlockRead (f2,buff,1); // считываем файл по 1 байту


conR: =conR+IntToBin (buff); // переводим считанный байт в двоичное число


prog: =prog+1;


end;


if length (conR) >=16 then // проверяем длину переменной


Дальнейший код основан на проверке определенных элементов кодовых слов. Так как кодовые слова имеющие смещение отличаются от предыдущих кодовых слов без смещения появлением в начале кодового слова дополнительных нулей, то необходимо проверять всего два элемента в кодовом слове. Поэтому массив разбивается на промежутки, что ускоряет поиск подходящих кодовых слов. Для первых 6 элементов массива кодовых слов достаточно одного условия проверки.


begin


if conR [1] ='1' then


begin


conW: =copy (conR,1,2); // копируем кодовое слово


fori: =0 to1 do


begin


ifword [i] =conWthen // сравниваем массив кодовых слов в заданном промежутке с выделенным кодовым словом


begin


BlockWrite (f3, inf [i],1); // записываем полученный элемент в файл


Delete (conR,1,2); // удаляем кодовое слово


break; // прерываем цикл


end;


end;


end


else


if conR [2] ='1' then


begin


conW: =copy (conR,1,4);


for i: =2 to 5 do


begin


if word [i] =conW then


begin


BlockWrite (f3, inf [i],1);


Delete (conR,1,4);


Break;


end;


end;


end


else


if (conR [2] ='0') and (conR [3] ='1') then


begin


conW: =copy (conR,1,6);


for i: =6 to 13 do


begin


if word [i] =conW then


begin


BlockWrite (f3, inf [i],1);


Delete (conR,1,6);


Break;


end;


end;


end


else


if (conR [3] ='0') and (conR [4] ='1') then


begin


conW: =copy (conR,1,8);


for i: =14 to 29 do


begin


if word [i] =conW then


begin


BlockWrite (f3, inf [i],1);


Delete (conR,1,8);


Break;


end;


end;


end


else


if (conR [4] ='0') and (conR [5] ='1') then


begin


conW: =copy (conR,1,10);


for i: =30 to 61 do


begin


if word [i] =conW then


begin


BlockWrite (f3, inf [i],1);


Delete (conR,1,10);


Break;


end;


end;


end


else


if (conR [5] ='0') and (conR [6] ='1') then


begin


conW: =copy (conR,1,12);


for i: =62 to 125 do


begin


if word [i] =conW then


begin


BlockWrite (f3, inf [i],1);


Delete (conR,1,12);


Break;


end;


end;


end


else


if (conR [6] ='0') and (conR [7] ='1') then


begin


conW: =copy (conR,1,14);


for i: =126 to 253 do


begin


if word [i] =conW then


begin


BlockWrite (f3, inf [i],1);


Delete (conR,1,14);


Break;


end;


end;


end


else


if (conR [7] ='0') and (conR [8] ='1') then


begin


conW: =copy (conR,1,16);


for i: =254 to 255 do


begin


if word [i] =conW then


begin


BlockWrite (f3, inf [i],1);


Delete (conR,1,16);


Break;


end;


end;


end;


if (EOF (f2) = true) and (length (conR) >1) then


// проверяем остаток


begin


for j: =1 to length (conR) do // считаем длину остатка


begin


if conR='' then break;


Проверка на остаток производится аналогично предыдущей процедуре. Поиск кодовых слов в остатке производится путем проверки определенных элементов кодовых слов. Сравнение и запись идентичны.


ifconR [1] ='1' then


begin


conW: =copy (conR,1,2);


for i: =0 to 1 do


begin


if word [i] =conW then


begin


BlockWrite (f3, inf [i],1);


delete (conR,1,2);


break;


end;


end;


end


else


if (conR [1] ='0') and (conR [2] ='1') then


begin


conW: =copy (conR,1,4);


for i: =2 to 5 do


begin


if word [i] =conW then


begin


blockWrite (f3, inf [i],1);


delete (conR,1,4);


break;


end;


end;


end


else


if (conR [2] ='0') and (conR [3] ='1') then


begin


conW: =copy (conR,1,6);


for i: =6 to 13 do


begin


if word [i] =conW then


begin


BlockWrite (f3, inf [i],1);


Delete (conR,1,6);


break;


end;


end;


end


else


if (conR [3] ='0') and (conR [4] ='1') then


begin


conW: =copy (conR,1,8);


for i: =14 to 29 do


begin


if word [i] =conW then


begin


BlockWrite (f3, inf [i],1);


Delete (conR,1,8);


break;


end;


end;


end


else


if (conR [4] ='0') and (conR [5] ='1') then


begin


conW: =copy (conR,1,10);


for i: =30 to 61 do


begin


if word [i] =conW then


begin


BlockWrite (f3, inf [i],1);


Delete (conR,1,10);


break;


end;


end;


end


else


if (conR [5] ='0') and (conR [6] ='1') then


begin


conW: =copy (conR,1,12);


for i: =62 to 125 do


begin


if word [i] =conW then


begin


BlockWrite (f3, inf [i],1);


Delete (conR,1,12);


break;


end;


end;


end


else


if (conR [6] ='0') and (conR [7] ='1') then


begin


conW: =copy (conR,1,14);


for i: =126 to 253 do


begin


if word [i] =conW then


begin


BlockWrite (f3, inf [i],1);


Delete (conR,1,14);


break;


end;


end;


end


else


if (conR [7] ='0') and (conR [8] ='1') then


begin


conW: =copy (conR,1,16);


for i: =254 to 255 do


begin


if word [i] =conW then


begin


BlockWrite (f3, inf [i],1);


Delete (conR,1,16);


break;


end;


end;


end;


end;


end;


end;


ProgressBar1.Position: =Round ( (prog/size) *100);


end;


Label6.Caption: =IntToStr (FileSize (f3)) + ' байт';


ShowMessage ('Процедура завершена');


end;


CloseFile (f3);


CloseFile (f2);


end;


procedure TForm1.FormCreate (Sender: TObject);


begin


for i: =0 to 255 do


a [i]: =0;


e [i]: =i;


end;


end.



Рис.1. Интерфейс программы


Результаты тестирования приложения:


Работа приложения тестировалась на различных типах файлов. Использовались файлы графического, текстового, мультимедийного и других форматов. Все данные о процессах сжатия изложены в следующей таблице.


















































Имятип файла Размер до сжатия Имя сжатого файла Размер после сжатия Сжатие
8bit org.bmp 68,7 КБ 8bit org.bmp.gop 18,1 КБ 73%
24bit org.bmp 203 КБ 24bitorg.bmp.gop 54,1 КБ 73%
DOC org.doc 1516 КБ DOC org.doc.gop 843 КБ 45%
RTF org.rtf 711 КБ RTF org.rtf.gop 539 КБ 24%
TXT org.txt 1 619 байт TXT org.txt.gop 1 392 байт 14%
midi org.mid 40 075 байт midi org.mid.gop 36 551 байт 9%
Unit1 org.pas 15 721 байт Unit1 org.pas.gop 9 068 байт 42%

Максимальный размер сжатия составляет 73-75%. В данной таблице отображены форматы файлов, которые можно было сжать. Однако некоторые форматы в связи со своей спецификой несут в себе определенные методы сжатия данных, что не позволяет приложению производить операции над ними. К таким форматам относятся: *.tiff, *.gif, *.wav, *.jpeg, *.avi, *.mp3, *.3gp, *.odt.


Процент сжатия характеризуется длиной кодовых слов и смещением. В данном случае максимальный процент сжатия будет 75%, так как минимальная длина кодового слова равна 2. Сжатие файла происходит побайтово, следовательно заменяем кодовым словом из 2 бит блоки из 8 бит.


Лучше всего подвергаются сжатию текстовые документы, менее сжимаемы и плохо сжимаемы мультимедия файлы.

Сохранить в соц. сетях:
Обсуждение:
comments powered by Disqus

Название реферата: Разработка программы сжатия и восстановления файлов с помощью фиксированного блочного кода постоянного смещения

Слов:2473
Символов:24241
Размер:47.35 Кб.