Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Курсовая работа тема Архиватор.doc
Скачиваний:
58
Добавлен:
01.04.2014
Размер:
476.67 Кб
Скачать
  1. Руководство пользователя

В этом разделе дается подробное описание использования данной программы. Элементы главной формы, используемые в описании, приводятся на рисунке 7.

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

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

  2. В поле ввода файла архива ввести имя файла архива с полным путем к нему. Для этого можно вызвать стандартное окно выбора файла на жестком диске, нажав на кнопку, расположенную справа от данного поля.

  3. Нажать кнопку «кодировать» для архивации, либо кнопку «декодировать» для деархивации.

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

  5. По окончании процесса архивации/деархивации в области информационного поля появится соответствующее сообщение.

Рисунок 7. Элементы главной формы программы.

  1. Список литературы

  1. Обучающий курс «Конструирование программ и языки программирования», часть 1. «Программирование на языке Си». Для студентов второго курса дистанционного обучения специальности «Программное обеспечение информационных технологий». Автор – Бахтизин В.В. , Минск 2003.

  2. Обучающий курс «Конструирование программ и языки программирования», часть 2. «Программирование на языке Ассемблер». Для студентов второго курса дистанционного обучения специальности «Программное обеспечение информационных технологий». Автор – Бахтизин В.В. , Минск 2003.

  3. Журнал Монитор выпуск №1, 1994 год. Цикл статей. «Алгоритмы сжатия информации», Мастрюков Д. Часть 2. «Арифметическое кодирование».

  4. Кент Рейсдорф и Кен Хендерсон, «Borland C++ Builder. Освой самостоятельно».

  1. Листинги программы

Листинг 1. Заголовочный файл формы Unit1.h

//------------------------------------------------------------------------------

#ifndef Unit1H

#define Unit1H

//------------------------------------------------------------------------------

#include <Classes.hpp>

#include <Controls.hpp>

#include <StdCtrls.hpp>

#include <Forms.hpp>

#include <Buttons.hpp>

#include <ExtCtrls.hpp>

#include <Dialogs.hpp>

#include <ExtDlgs.hpp>

#include <ComCtrls.hpp>

#include <Menus.hpp>

//------------------------------------------------------------------------------

class TForm1 : public TForm

{

__published: // IDE-managed Components

TButton *Button1; //Кнопка "Кодировать"

TLabeledEdit*LabeledEdit1; //Поле ввода пути к каталогу

TSpeedButton *SpeedButton1; //Кнопка выбора пути к каталогу

TLabeledEdit *LabeledEdit2; //Поле ввода имени файла архива

TSpeedButton *SpeedButton2; //Кнопка ввода имени файла архива

TButton *Button2; //Кнопка "Декодировать"

TLabel *Label1; //Информационная надпись

TSaveDialog *SaveDialog1; //Компонент диалога сохранения файлов

TProgressBar *ProgressBar1; //Индикатор состояния процесса

TMainMenu *MainMenu1; //Компонент главного меню формы

TMenuItem *N1; //Кнопка главного меню "О программе"

void __fastcall Button1Click(TObject *Sender);

void __fastcall Button2Click(TObject *Sender);

void __fastcall SpeedButton1Click(TObject *Sender);

void __fastcall SpeedButton2Click(TObject *Sender);

void __fastcall N1Click(TObject *Sender);

private: // User declarations

public: // User declarations

__fastcall TForm1(TComponent* Owner);

};

//------------------------------------------------------------------------------

extern PACKAGE TForm1 *Form1;

//------------------------------------------------------------------------------

#endif

Листинг 2. Файл кода формы Unit1.cpp

//------------------------------------------------------------------------------

#include <vcl.h>

#include <stdio.h>

#include <FileCtrl.hpp>

#include "Unit1.h"

#include "Unit2.h"

#pragma hdrstop

//------------------------------------------------------------------------------

#pragma package(smart_init)

#pragma resource "*.dfm"

// Количество битов в регистре. 16 Вполне достаточно для 256 символов

#define BITS_IN_REGISTER 16

// Максимально возможное значение в регистре

#define TOP_VALUE (((long) 1 << BITS_IN_REGISTER) - 1)

// Диапазоны

#define FIRST_QTR (TOP_VALUE / 4 + 1) //Первая четверть

#define HALF (2 * FIRST_QTR) //Вторая четверть

#define THIRD_QTR (3 * FIRST_QTR) //Третья четверть

#define NO_OF_CHARS 256 // Количество символов алфавита

#define EOF_SYMBOL (NO_OF_CHARS + 1) // Специальный символ "Конец Файла"

#define NO_OF_SYMBOLS (NO_OF_CHARS + 1) // Всего символов в модели

// Порог частоты для масштабирования 16383 в нашем случае

#define MAX_FREQUENCY (((long) 1 << BITS_IN_REGISTER-2) - 1)

// Таблицы пеpекодиpовки исходных и рабочих символов

unsigned char index_to_char [NO_OF_SYMBOLS]; //Из рабочего в исходный

short int char_to_index [NO_OF_CHARS]; //Из исходного в рабочий

// Таблицы частот

short int cum_freq [NO_OF_SYMBOLS + 1]; //Суммарные частоты (с учетом менее

//встречаемых символов рабочего алфавита)

short int freq [NO_OF_SYMBOLS + 1]; // частоты (без учета менее

//встречаемых символов рабочего алфавита)

// Регистры границ и кода

unsigned short int low, high; // Нижняя и верхняя границы текущего интервала

unsigned short int value; //Текущее значение части входного числа(используется

//только при деархивации)

// Поддержка побитлвых операций с файлами

long bits_to_follow; // Количество подряд идущих "1" либо "0", хранящихся в

//памяти для предотвращения отрицательного переполнения

short int buffer; // Переменная используемая для накопления отдельных битов

//перед записью в файл при кодировании,

//либо хранения после чтения из файла при декодировании

short int bits_to_go; //Количество свободных в буфере битов при кодировании,

//либо занятых при декодированни;

// Обрабатываемые файлы

FILE *in,*out; // соответственно входной и выходной файлы

struct spisok //Структура записи динамического списка файлов текущей папки

//при кодировании, либо файлов в архиве при декодировании

{

char *filename; //Указатель на строку, содержащую относительный путь к файлу

//и имя самого файла

struct spisok *nextPtr; // указатель на следующий элемент списка

};

typedef struct spisok Spisok; // Всю структуру определяем как "Spisok"

typedef Spisok * SpisokPtr; //а указатель на нее как "SpisokPtr"

SpisokPtr headPtr=NULL; //Указатель на первый элемент списка

SpisokPtr tekPtr=NULL; //Указатель на текущий элемент списка

AnsiString Path0; // Путь текущего каталога

AnsiString Path1; // Относительные пути к файлам (относительно текущего каталога)

// Path0+Path1 образует полный путь к файлу

unsigned short int nf; //количество файлов в архиве

TForm1 *Form1; //Главная форма программы архиватора

//------------------------------------------------------------------------------

//Эту процедуру сделала среда разработки, я пока не знаю, для чего она

__fastcall TForm1::TForm1(TComponent* Owner)

: TForm(Owner)

{

}

//------------------------------------------------------------------------------

// Инициализация адаптивной модели

void start_model (void)

{

int i;

// Установка таблиц пеpекодиpовки между исходными и рабочими символами

for ( i = 0; i < NO_OF_CHARS; i++)

{

char_to_index [i] = i + 1;

index_to_char [i + 1] = i;

}

for ( i = 0; i <= NO_OF_SYMBOLS; i++)

{

freq [i] = 1; //Установка значений счетчиков частот в 1 для всех символов

cum_freq [i] = NO_OF_SYMBOLS - i; //Установка значений суммарных частот

}

freq [0] = 0; //freq[0] должен быть меньше freq[1], чтобы процедура обновления

//таблиц перекодировки работала корректно

}

//------------------------------------------------------------------------------

// Обновление модели очередным символом, входной параметр-индекс нового символа

void update_model ( int symbol)

{

short int i; // Новый индекс этого символа

short int ch_i; // Символ рабочего алфавита, соответствующий i

short int ch_symbol; // Символ рабочего алфавита, соответствующий symbol

// масштабирование частот при переполнении

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

if (cum_freq [0] == MAX_FREQUENCY)// Если счетчики частот достигли максимума

{

short int cum=0; //Переменная, в которой накапливается суммарная частота

for ( i = NO_OF_SYMBOLS; i >= 0; i--)

{

freq [i] = (freq [i] + 1) / 2; //Тогда делим их всех пополам,

//не приводя к нулю

cum_freq [i] = cum; //Обновляем суммарные частоты

cum += freq [i];

}

}

//Находим самый малый символ в таблице с такой же частотой

for ( i = symbol; freq [i] == freq [i - 1]; i--);

if (i < symbol) //Если он меньше нового символа, то

{ //меняем их местами, в обоих таблицах

ch_i = index_to_char [i];

ch_symbol = index_to_char [symbol];

index_to_char [i] = ch_symbol;

index_to_char [symbol] = ch_i;

char_to_index [ch_i] = symbol;

char_to_index [ch_symbol] = i;

}

// обновление значений в таблицах частот

freq [i] += 1; //увеличиваем частоту нового символа

for(;i>0;++cum_freq [--i]); //увеличиваем суммарные частоты более частых

//символов;

}

//------------------------------------------------------------------------------

// Инициализация побитового ввода

void start_inputing_bits (void)

{

bits_to_go = 0; //Количество занятых в буфере битов перед декодированием 0

}

//------------------------------------------------------------------------------

// Ввод очередного бита сжатой информации, возвращает очередной бит

int input_bit (void)

{

int t; //Переменная, в которой будет хранится введенный бит

if (bits_to_go == 0)//Если буфер пустой

{

buffer = getc(in); //считываем очередной символ из файла

bits_to_go = 8; //количество занятых битов устанавливаем 8

}

t = buffer & 1; //помещаем в t значение младшего бита буфера

buffer >>= 1; //сдвигаем буфер на 1 бит вправо

bits_to_go-- ; //уменьшаем количество занятых битов

return t; //возвращаем значение t

}

//------------------------------------------------------------------------------

// Инициализация побитового вывода

void start_outputing_bits (void)

{

bits_to_go = 8; //устанавливаем количество свободных битов буфера 8

buffer = 0; //устанавливаем значение буфера 0

}

//------------------------------------------------------------------------------

// Вывод очередного бита сжатой информации, входной параметр-выходной бит

void output_bit ( int bit)

{

buffer >>= 1; //сдвигаем буфер на 1 вправо, чтобы освободить место

//старшего бита очередному биту

if (bit) //если очередной бит равен 1, то

buffer |= 0x80; //в старший бит буфера устанавливаем 1

bits_to_go-- ; //уменьшаем количество свободных битов буфера

if (bits_to_go == 0) //Если свободных битов не осталось, то

{

putc ( buffer, out); //Записываем буфер в выходной файл

bits_to_go = 8; //устанавливаем количество свободных битов буфера 8

}

}

//------------------------------------------------------------------------------

// Очистка буфера побитового вывода

void done_outputing_bits (void)

{ //записываем в выходной файл значение буфера, сдвинутое на количество

putc ( buffer >> bits_to_go, out); //свободных битов

}

//------------------------------------------------------------------------------

// Вывод указанного бита и отложенных ранее, входной параметр-выходной бит

void output_bit_plus_follow (short int bit)

{

output_bit (bit); //заносим выходной бит в буфер

//и вслед за ним количество отложенных ранее противоположных битов

for( ; bits_to_follow > 0; bits_to_follow-- ) output_bit (!bit);

}

//------------------------------------------------------------------------------

// Инициализация регистров границ и кода перед началом сжатия

void start_encoding (void)

{

low = 0; //в нижней границе устанавливаем все нули

high = TOP_VALUE; //в верхней - все единицы

bits_to_follow = 0; //количество отложенных битов устанавливаем 0

}

//------------------------------------------------------------------------------

// Завершение кодирования потока

void done_encoding (void)

{

bits_to_follow++; //Здесь происходит вывод двух битов

if (low < FIRST_QTR) //определяющих четверть, лежащую в

output_bit_plus_follow (0); //текущем интервале

else

output_bit_plus_follow (1);

}

//------------------------------------------------------------------------------

// Инициализация регистров перед декодированием.

// Загрузка начала сжатого сообщения

void start_decoding (void)

{

int i;

value = 0; //Все биты части входного сигнала заполняем

for ( i = 1; i <= BITS_IN_REGISTER; i++) //начальными битами

value = 2 * value + input_bit (); //входного файла

low = 0; //в нижней границе устанавливаем все нули

high = TOP_VALUE; //в верхней - все единицы

}

//------------------------------------------------------------------------------

// Кодирование очередного символа, входной параметр - кодируемый символ

void encode_symbol ( int symbol)

{

long range; //Шиpина текущего кодового интервала

range = (long) (high - low) + 1; //Сужение интервала кодов

//до выделенного для symbol

// пересчет значений границ, соответственно верхней и нижней

high = low + (range * cum_freq [symbol - 1]) / cum_freq [0] - 1;

low = low + (range * cum_freq [symbol]) / cum_freq [0];

// выдвигание очередных битов

for (;;) //Цикл с заранее неизвестным числом повторений

{

if (high < HALF) //Если в обоих границах старшие биты нули,

output_bit_plus_follow (0); //то выводим 0

else if (low >= HALF) //Если в обоих границах старшие биты единицы,

output_bit_plus_follow (1); //то выводим 1

else if (low >= FIRST_QTR && high < THIRD_QTR)

{ //Если текущий интервал содержит середину исходного,

bits_to_follow += 1;//то вывод еще одного обратного бита позже,

low -= FIRST_QTR; //а сейчас убрать общую часть

high -= FIRST_QTR;

}

else break; //Иначе выйти из цикла

// Расширить текущий рабочий кодовый интервал

// сдвигом влево с "втягиванием" очередного бита

low <<=1; //В младший байт нижней границы втягивается 0

high<<=1;

high++; //В младший байт верхней границы втягивается 1

}

}

//------------------------------------------------------------------------------

// Декодирование очередного символа, возвращает символ рабочего алфавита

int decode_symbol (void)

{

long range; //Ширина текущего кодового интервала

int cum; //Суммарная частота для текущего символа

int symbol; //Значение символа рабочего алфавита

range = (long) (high - low) + 1;//определение текущего масштаба частот

// масштабирование значения в регистре кода

cum = (int)((((long) (value - low) + 1) * cum_freq [0] - 1) / range);

// поиск соответствующего символа в таблице частот

for (symbol = 1; cum_freq [symbol] > cum; symbol++);

// пересчет границ

high = low + (range * cum_freq [symbol - 1]) / cum_freq [0] - 1;

low = low + (range * cum_freq [symbol]) / cum_freq [0];

// удаление очередного символа из входного потока

for (;;) //Цикл с заранее неизвестным числом повторений

{

if (high >= HALF) //Если старший бит верхней границы 1,то

if (low < HALF) //Если младший бит нижней границы 0,то

if (low < FIRST_QTR || high >= THIRD_QTR)//Если текущий интервал не

break; //содеpжит сеpедину исходного, то выходим из цикла

else //Иначе

{ //Убираем общую часть

value -= FIRST_QTR;

low -= FIRST_QTR;

high -= FIRST_QTR;

}

// сдвиг влево с втягиванием очередного бита

low <<=1; //В младший байт нижней границы втягивается 0

high<<=1;

high++; //В младший байт верхней границы втягивается 1

value<<=1;

value+=input_bit(); //В текущее значение части входного числа

} //втягивается следующий бит

return symbol; //Возвращаем значение символа рабочего алфавита

}

//------------------------------------------------------------------------------

//Добавление файла в динамический список, входной параметр- указатель на

//имя файла

void addfile(char *fn)

{

char *st; //Указатель на строку, содержащую имя файла и относительный

//путь к нему

SpisokPtr newPtr; //Указатель на новый элемент списка

st=(char*)malloc(strlen(fn)+strlen(Path1.c_str())+1); //Выделяем память

//для хранения строки, содержащей имя файла и относительный путь к нему

strcpy(st,Path1.c_str());//Копируем относительный путь

strcat(st,fn); //Добавляем имя файла

newPtr=(Spisok*)malloc(sizeof(Spisok));//Выделяем память под новый

//элемент списка

newPtr->filename=st; //Ставим в соответствие указателю на строку в

//элементе списка, указатель на созданную строку

if (headPtr==NULL) //Если список до этого не содержал ни одного

//элемента,то

headPtr=newPtr; //делаем его первым элементом списка

else tekPtr->nextPtr=newPtr; //иначе вставляем его после текущего

tekPtr=newPtr; //делаем новый элемент списка текущим

tekPtr->nextPtr=NULL; //Помещаем в указатель на следующий элемент NULL

}

//------------------------------------------------------------------------------

//Обход файлов текущего каталога и всех его подкаталогов(всего дерева)

void obhod(void)

{

TSearchRec sr; //Структура хранящая информацию о найденных файлах

if (FindFirst("*", faAnyFile, sr) == 0) //Ищем первый файл

{

do

{ //Если текукщий файл - не является каталогом, то

if ((sr.Attr & faDirectory) != faDirectory )

{

char filename[MAX_PATH]; //Массив символов, содержащий имя файла

strcpy(filename,sr.Name.c_str());//Копируем в него имя файла

addfile(filename); //Добавляем его в динамический список файлов

nf++; //Увеличиваем количество файлов в архиве

}

}

while (FindNext(sr) == 0); //Пока не нашли все файлы в каталоге

// обработка подкаталогов текущего каталога

if (FindFirst("*", faDirectory, sr) == 0 ) //Если, предположительно,

//нашли каталог

do

{

if ((sr.Attr & faDirectory) == faDirectory) //Если он действительно

//является каталогом

if (sr.Name[1] != '.' ) //Если это не указатель на родительский

{ //каталог

AnsiString olds=Path1;//Сохраняем относительный путь в строке olds

Path1+=sr.Name+"\\"; //Добавляем к имени относительного пути имя

//найденного каталога и наклонную черту

ChDir(sr.Name);// входим в каталог

obhod(); // выполняем поиск в подкаталоге

Path1=olds; // Возвращаем относительный путь

ChDir(".."); // выходим из каталога

}

}

while (FindNext(sr)==0); //пока не нашли все подкаталоги в текущем каталоге

FindClose(sr); //закрываем поиск

}

}

//------------------------------------------------------------------------------

//Функщия, которая выполняется перед каждым сеансом кодирования и декодирования

void start(void)

{

char buf[MAX_PATH]; //Массив символов, в котором производится преобразование

//пути каталога архивирования

char *p; //указатель для поиска в нем символа '\'

nf=0; //Устанавливаем количество файлов в 0

tekPtr=headPtr; //Первый элемент списка делаем текущим

strcpy(buf,Form1->LabeledEdit1->Text.c_str());//Копируем в buf строку из

//LabeledEdit1

p=strchr(buf,0); //ставим указатель p на символ конца строки buf

if(*(p-1)!='\\') //если последний символ строки buf не '\', то

strcpy(p,"\\"); //добавляем к строке '\'

Path0=AnsiString(buf); //В Path0 записываем полученную строку

ForceDirectories(Path0);//Создаем каталог, если его не существует

ChDir(Path0); //Входим в него

Path1=""; //Относительный путь равен пустой строке

}

//------------------------------------------------------------------------------

//Функщия, которая выполняется после каждого сеанса кодирования и декодирования

void end(void)

{

SpisokPtr prevPtr; //Указатель на предыдущий элемент списка

tekPtr=headPtr; //Текущим элементом списка делаем первый

while (tekPtr!=NULL) //Пока текущий элемент не равен NULL

{

prevPtr=tekPtr; //Сохраняем указатель на текущий элемент в prevPtr

tekPtr=tekPtr->nextPtr; //tekPtr переводим на следующий элемент

free(prevPtr->filename); //Освобождаем память строки имени файла предыдущего

//элемента списка

free(prevPtr); //Освобождаем память от предыдущего элемента списка

}

headPtr=NULL; // headPtr устанавливаем в NULL

}

//------------------------------------------------------------------------------

// Собственно адаптивное арифметическое кодирование

// Входной параметр - имя выходного файла

void encode (char *outfile)

{

int ch; //Переменная, в которую считывается очередной символ исходного

//алфавита из входного файла

int symbol; //соответствующий ему символ рабочего алфавита

start(); //вызоваем функцию start

obhod(); //обходим все файлы каталога и подкаталогов

Form1->ProgressBar1->Max=nf; //Делаем максимальное значение индикатора

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

Form1->ProgressBar1->Position=0;//Устанавливаем значение индикатора

//состояния процесса в 0

Form1->Label1->Visible=False; //Делаем невидимой строку информации

Form1->ProgressBar1->Visible=True;//Делаем видимым индикатор состояния процесса

out = fopen ( outfile, "w+b"); //Открываем файл архива для перезаписи

if (out == NULL) // если файл не создается, то сообщаем об этом пользователю

{

Form1->Label1->Caption="Не получается создать файл архива!";

Form1->ProgressBar1->Visible=False;

Form1->Label1->Visible=True;

return; //Завершаем процесс

}

fwrite(&nf,2,1,out); //Записываем в начало архива количество файлов

//Записываем список файлов с относительными путями в начало архива

tekPtr=headPtr; //Делаем первый элемент списка текущим

while (tekPtr!=NULL) //Пока не достигнут конец списка

{

fprintf(out,"%s\n",tekPtr->filename);//Записываем имя файла с относительным

//путем к нему в файл архива

tekPtr=tekPtr->nextPtr; //Переходим к следующему файлу в списке

}

start_model (); //Производим инициализацию адаптивной модели

start_outputing_bits (); //Производим инициализацию побитового вывода

start_encoding (); //Производим инициализация регистров границ и кода перед

//началом сжатия

//Производим последовательное кодирование всех файлов списка

tekPtr=headPtr; // Делаем первый элемент списка текущим

while (tekPtr!=NULL) //Пока не достигнут конец списка

{

char infile[MAX_PATH]; //переменная, в которой хранится имя входного файла

strcpy(infile,tekPtr->filename); //копируем в нее имя текущего файла списка

tekPtr=tekPtr->nextPtr; //переходим к следующему файлу списка

in = fopen ( infile, "rb"); //открываем этот файл для чтения

if (in == NULL) continue; //если он не открывается, то продолжаем

for (;;) //Цикл с заранее неизвестным числом повторений

{

ch = getc (in); //считываем очередной символ исходного алфавита из файла

if (ch == EOF) break; //если достигнут конец файла, то выходим из цикла

symbol = char_to_index [ch]; //находим соответствующий ему символ рабочего алфавита

encode_symbol (symbol); //кодируем этот символ

update_model (symbol); //обновляем модель очередным символом

}

encode_symbol (EOF_SYMBOL); //При выходе из цикла кодируем символ конца файла

fclose (in); //Закрываем входной файл

Form1->ProgressBar1->Position++; //Увеличиваем значение индикатора на 1

}

done_encoding (); //Производим завершение кодирования потока

done_outputing_bits(); //Очистка буфера побитового вывода

fclose (out); //Закрываем файл архива

end(); //вызываем функцию end

Form1->ProgressBar1->Visible=False; //Прячем индикатор состояния процесса

Form1->Label1->Caption="Архивация завершена"; //Выводим сообщение пользователю

Form1->Label1->Visible=True; //Делаем его видимым

}

//------------------------------------------------------------------------------

//Функция выделяющая из строки имени файла относительный путь к нему, и

//создающая этот каталог, входной параметр - имя файла

void makedir(char *filename)

{

if(strchr(filename,'\\')!=NULL) //Если имя файла содержит '\', то

{

char buf[MAX_PATH]; //Переменная, в которой будет происходить преобразование

//имени файла

char *p; //вспомогательный указатель

strcpy(buf,filename); //Копируем в buf имя файла

p=strchr(buf,0); //запоминаем в p конец строки

for(;*p!='\\';p--); //Уменьшаем p пока он не указывает на '\'

*p=0; //Ставим на место '\' символ конца строки

Path1=AnsiString(buf); //Делаем преобразованную строку относительным путем

ForceDirectories(Path0+Path1); //Создаем такую директорию, если ее не существует

}

}

//------------------------------------------------------------------------------

// Собственно адаптивное арифметическое декодирование,

//входной параметр - имя файла архива

void decode ( char *infile)

{

SpisokPtr tekPtr; //указатель на текущий элемент списка

int symbol; //Переменная, в которую считывается очередной символ рабочего

//алфавита из файла архива

int ch; //соответствующий ему символ исходного алфавита

in = fopen ( infile, "rb"); //Открываем файл архива для чтения

if (in == NULL) //Если он не открывается, то

{ //выводим об этом сообщение пользователю

Form1->Label1->Caption="Не получается открыть файл архива!";

Form1->Label1->Visible=True; //Делаем его видимым

Form1->ProgressBar1->Visible=False; //Скрываем индикатор состояния

return; //Завершаем процесс

}

start(); //вызоваем функцию start

fread(&nf,2,1,in);//Считываем количество файлов в архиве (первые 2 байта)

Form1->ProgressBar1->Max=nf; //Делаем максимальное значение индикатора

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

Form1->ProgressBar1->Position=0;//Устанавливаем значение индикатора

//состояния процесса в 0

Form1->Label1->Visible=False; //Делаем невидимой строку информации

Form1->ProgressBar1->Visible=True;//Делаем видимым индикатор состояния процесса

//Заносим список файлов в динамический список, выполняя количество чтений

for(int i=0;i<nf;i++) //равное числу файлов в архиве

{

int dl; //переменная, в которой хранится длина строки имени файла

char filename[MAX_PATH]; //массив, в котором хранится имя файла

fgets(filename,MAX_PATH,in); //считываем в него очередную строку

dl=strlen(filename); //выясняем ее длину

strcpy(&filename[dl-1],"\0"); //убираем из имени файла лишние символы

addfile(filename); //добавляем имя файла в динамический список

};

start_model (); //Производим инициализацию адаптивной модели

start_inputing_bits (); //Производим инициализацию побитового ввода

start_decoding (); //Производим инициализацию регистров перед декодированием

//и загрузку начала сжатого сообщения

tekPtr=headPtr; //Делаем первый элемент списка текущим

makedir(tekPtr->filename); //выделяем из строки имени файла относительный путь

//к нему, и создаем этот каталог, если его не существует

out = fopen ( tekPtr->filename, "w+b"); //Перезаписываем первый файл

for (;;) //Цикл с заранее неизвестным числом повторений

{

symbol = decode_symbol ();//Декодируем очередной символ рабочего алфавита

if (symbol == EOF_SYMBOL) //Если он равен символу конца файла, то

{

fclose (out); //Закрываем текущий файл

Form1->ProgressBar1->Position++; //Увеличиваем значение индикатора на 1

tekPtr=tekPtr->nextPtr; //Переходим к следующему элементу списка

if (tekPtr==NULL) //Если достигнут конец списка, то

break; //выходим из цикла

else //иначе

{

makedir(tekPtr->filename); //выделяем из строки имени файла

//относительный путь к нему, и создаем этот каталог, если его не существует

out = fopen( tekPtr->filename, "wb"); //Перезаписываем текущий файл

continue; //Продолжаем цикл

}

}

ch = index_to_char [symbol]; //Очередному символу рабочего алфавита,

//находим соответствующий символ исходного

putc ( ch, out); //записываем его в выходной файл

update_model (symbol); //обновляем модель очередным символом

}

fclose (in); //Закрываем файл архива

end(); //вызываем функцию end

Form1->ProgressBar1->Visible=False; //Прячем индикатор состояния процесса

Form1->Label1->Caption="Деархивация завершена"; //Выводим сообщение

Form1->Label1->Visible=True; //Делаем его видимым

}

//------------------------------------------------------------------------------

//Нажатие кнопки "Кодировать"

void __fastcall TForm1::Button1Click(TObject *Sender)

{

char outfile[MAX_PATH]; //Массив, в котором хранится имя выходного файла

strcpy(outfile,LabeledEdit2->Text.c_str()); //Копируем в него имя файла,

//введенное в строку ввода LabeledEdit2

char *p=strchr(outfile,'.');//В переменной p сохраняем указатель на символ '.'

if(p) //если имя файла содержит точку, то

strcpy(p,".ar"); //начиная с нее копируем строку ".ar"

else strcat(outfile,".ar"); //иначе добавляем к имени файла строку ".ar"

encode(outfile); //Вызываем функцию кодирования с получившимся именем файла

}

//------------------------------------------------------------------------------

//Нажатие кнопки "Декодировать"

void __fastcall TForm1::Button2Click(TObject *Sender)

{

char infile[MAX_PATH]; //Массив, в котором хранится имя входного файла

strcpy(infile,LabeledEdit2->Text.c_str()); //Копируем в него имя файла,

//введенное в строку ввода LabeledEdit2

decode(infile); //Вызываем функцию декодирования с получившимся именем файла

}

//------------------------------------------------------------------------------

//Нажатие кнопки выбора пути текущего каталога

void __fastcall TForm1::SpeedButton1Click(TObject *Sender)

{

AnsiString dir; //Строка, которая будет содержать путь к каталогу

if (SelectDirectory("Укажите путь","",dir)) //Если был выбран путь, то

LabeledEdit1->Text=dir; //заносим его в LabeledEdit1

}

//------------------------------------------------------------------------------

//Нажатие кнопки выбора файла архива

void __fastcall TForm1::SpeedButton2Click(TObject *Sender)

{

SaveDialog1->InitialDir=LabeledEdit1->Text; //В InitialDir устанавливаем

//LabeledEdit1

if (SaveDialog1->Execute()) //Если был выбран файл архива, то

LabeledEdit2->Text=SaveDialog1->FileName; //заносим его имя в LabeledEdit2

}

//------------------------------------------------------------------------------

//Нажатия кнопки "О программе"

void __fastcall TForm1::N1Click(TObject *Sender)

{

Form1->Hide(); //Прячем главную форму

Form2->ShowModal(); //Показываем модально окно "О программе"

Form1->Show(); //Показываем главную форму

}

//------------------------------------------------------------------------------