Failu arhivēšana

ANOTĀCIJA

Kvalifikācijas darba pārskats izklāstīts 28. lappusēs, tajā ietilpst 7. nodaļas, pielikumu, 4. zīmējumus.
Pārskatā tiek aprakstīti datu arhivēšanas metode, tiek precizēti prasības programmai. Kā arī sniegta lietotāja instrukcija. Ka arī paradīts programmas funkcionēšanas kontroles piemērs.
Programma sastādīta valodā TURBO PASCAL 7.0 un atrisināta ar Pentium166 MMX datoru, operētājsistēmas MS-DOS vidē.

АНОТАЦИЯ

Отчет состоит из: 28 страниц, 7 разделов, одного приложения и 4 рисунков.
В отчете описаны принципы архивирования данных, конкретизированы требования к программе. Написана инструкция пользователю. Показан пример функционирования программы.
Программа реализована на языке TURBO PASCAL 7.0, на компьютере Pentium166 MMX, в операционной системе MS-DOS.

SATURS

IEVADS 5
1. TEORETISKĀ DAĻA 6
1.1. Problēmu apraksts 6
1.2. Metodes apraksts 6
1.3. Izmantota metode 6
2. PRAKTISKĀ DAĻA 9
2.1. Uzdevuma nostādne 9
2.2. Algoritma apraksts 10
2.3. Programmas apraksts 11
2.3.1. Lietojumsfēra 11
2.3.2. Ievaddati 11
2.3.3. Izvaddati 11
2.3.4. Ziņas par programmas apjomu un izpildes laiku 11
2.3.5. Moduļu apraksts 12
2.3.6. Procedūru un funkciju apraksts 12
3. LIETOTĀJA INSTRUKCIJA 14
4. PROGRAMMAS FUNKCIONĒŠANAS KONTROLES PIEMĒRS 15
5. SECINĀJUMI 17
6. IZMANTOTA LITERATŪRA 18
7. PIELIKUMS 19

IEVADS

Lietotājam ir nepieciešamība pārnest failus no viena datora uz otru. Daudziem lietotājam nav datoru tiklu, kurā jūs varat kopēt failus, tad rasties nepieciešamība nokopēt failu uz disketi, bet faila izmērs varbūt lielāks par disketes ietilpību. Varbūt arī gadījums, kad lietotājam ir nepieciešams palielināt cieta diska brīvu vietu bez datu zaudējumiem. Šajos gadījumos es rekomendē izmantot programmas – arhivatorus (t.i. programmas, kuri ļauj samazināt failu izmērus bez datu zaudējumus).
Eksistē dažādas programmas – arhivatori, viņi strādā dažādās operātājsistēmās, piemēram Windows, Unix, MS-DOS. Es gribēju izstrādāt programmu – arhivatoru, kura strādā MS-DOS vidē, bet kurā jābūt labākam interfeisam neka ‘Arj’ vai ‘Zip’ arhivatoriem. Piemēram ‘Arj’ neizmanto krasus savā interfeisā un nevar strādāt bez komandas no komandas rinda. Manai programmai jāatbalsta komandas no komandas rinda, ka piemēram ‘Arj’, ‘Zip’ un jāatbalsta man vajadzīgu interfeisu, ka arī programmai ir jāstrādā bez komandas no komandas rinda.

TEORETISKĀ DAĻA

Problēmu apraksts

Daudzie lietotāji doma, kā samazināt faila izmērus, lai nokopēt to uz disketi vai palielināt cieta diska brīvu vietu bez datu zaudējumiem. Šī programma var samazināt faila izmērus (nokodēt) un kad ir nepieciešams, programma var atjaunot kodēta faila saturu (būs fails, ka pirms kodēšanai). Ja faila izmērs ir ļoti mazs un viņš sastāv no dažādiem simboliem, tad var iznākt, ka kodēta faila izmērs ir lielāks pār sākotnēja faila izmēru. Šajā situācijā es nerekomendē izmantot manu programmu ‘Arhivator’, tāpēc kā šeit viņa nepalīdzes jums.
Programma paredzēta faila izmēru samazināšanai (arhivēšanai) un faila atjaunošanai bez datu zaudējumu.

Metodes apraksts

Īsi apskatīsim arhivēšanas metodes, kuriem ir pietekami ilga vēsture. Vairāk informācijas jūs varat atrast grāmatās [3] [5].
Eksistē dažādas pieejas šī problēmai. Apskatīsim “neveiksmīgu” pieeju šī problēmai, tas RLE (Run Length Encoding) metode, viņš kode sērijas garumu. Šī metode aizvieto atkārtojamas simbolu virknes uz vienu simbolu un to atkārtojumu skaitu. Problēma ir sekojoša, atjaunošanas (uncoding) gaitā mums ir nepieciešams atšķirt kodētu sēriju no citiem simboliem. Risinājums ir sekojošs, pievienot šīm simbolu virknēm kaut kādu virsrakstu, piemēram izmantot pirmo bitu, kā kodētas virknes pazīme. Metode ir pietekami efektīva priekš grafisku attēlu formātā baits uz punktu (byte on pixel), piemēram formāts PCX izmanto kodēšanu RLE. Metodes trūkums ir zema samazināšanas pakāpe, piemēram tekstā bez divburtu vārdiem viņš var nokodēt tikai tukšas simbolu zīmes rindas sākumā.
LZW (Lempel Ziv Welch) metode vēsture sākas maijā 1977. gadā no raksta “IEEE Trans” publikācijas žurnālā “Информационные теории”, raksta autori bija Dž. Zivs (J. Ziv) un A. Lempels (A. Lempel). Pēc tām šo algoritmu uzlaboja Terri A. Velčems (Terry A. Welch) un pēdējā variantā šis algoritms bija atspoguļots rakstā “IEEE Computer” jūnijā 1984. gadā. Šī rakstā bija aprakstīti algoritma detaļas un dažādas realizācijas problēmas. Šis algoritms kode secīgus dažādus simbolus. Šis algoritms kodēšanas laikā “mācās”. Algoritma priekšrocība ir to, ka nav nepieciešams kodēta failā rakstīt simbolu kodu tabulu.

Izmantota metode

Aplūkosim arhivēšanas (kodēšanas) metodi, kurš tiek izmantots manā programmā:
Kodēšana (encoding) strādā ar datu plūsmu kaut kādā alfabētā, tajā laikā simbolu frekvence (atkārtojums) ir dažāda. Arhivēšanas mērķis ir datu plūsmas pārveidošana uz bitu plūsmu ar minimālu garumu To mēs varam iegūt samazinājot datu plūsmas entropīju, izmantojot simbolu frekvenci: kodu garumam jābūt proporcionālam informācijai, kurā ir ieejas plūsmā. Ja mēs zinam frekvences varbūtības sadalījumu, tad mēs varam iegūt optimālu kodēšanu. Uzdevums ir sarežģītāk gadījumā, ja simbolu frekvences sadalījums iepriekš nav zināms. Šajā gadījumā eksistē divas dažādas pieejas.
Pirmā pieeja: aplūkot ieejas datu plūsmu un uzbūvēt kodēšanu pamatojoties uz savākto statistiku (mums ir jālasa dati, kuri atrodas failā, divas reizes, kas ierobežo pielietošanas sfēru šādiem algoritmiem). Tādā gadījumā izmantotas kodēšanās shēmai jābūt uzrakstītai izejas datu plūsmā, kuru pēc tām dekoderis izmantojies. Piemēram statikas Hafmana kodēšana (Huffman).
Otrā pieeja izmanto, tā saucamo adaptīvo koderu (adaptive coder). Šajās pieejas galvena ideja ir mainīt kodēšanas shēmu atkarība no sākotnējas datu. Tādu algoritmu mēs pagājām tikai vienu reizi, jo viņam nav vajadzīga informācija pār kodēšanas izmantotu shēmu tieša veidā. Dekoderis, nolasot kodētu plūsmu, sinhroniski ar koderu maina kodēšanas shēmu, sākot ar kādu jau zināmu. Adaptīvā kodēšana var vairāk samazināt izejas datu plūsmas garumu, tāpēc ka varbūt paredzēti frekvences izmaiņas. Piemēram, dinamiska Hafmena kodēšana.
Aplūkosim statikas Hafmena kodēšanu. Šī kodēšana salīdzina ieejas simbolus (parasti tie ir dažāda garuma bitu ķēdes) ar mainīga garuma bitu ķēdi. Koda garums simboliem ir proporcionāls viņas frekvences bināram logaritmam, kurš ņemts ar pretējo zīmi. Šī kodēšana ir prefiksa, kas ļauj viegli to dekodēt (prefiksā kodēšanā kāda simbola kods neatbilsta cita simbola koda prefiksam).
Pieņemsim ka, ieejas alfabētā ir četri simboli: a, b, c, d, viņas frekvences ir atbilstoši vienādi ar 1/2, 1/4, 1/8, 1/8. Šim alfabētam Hafmena kodēšana izskatās šādi:

Simbols Frekvence Ieeja kods Izejas kods
a 1/2 00 0
b 1/4 01 10
c 1/8 10 110
d 1/8 11 111

Piemēram, ķēdes abaaacb kods ieejas plūsmā izskatās šādi: 00 01 00 00 00 10 01, bet izejas izskatās šādi: 0 10 0 0 0 110 10 (tukša vieta starp cipariem ir pievienota lai vieglāk lasītu). Ieejas mums bija 14 bitu, bet izejas mums ir ja 11 bitu. Hafmena kodēšana parasti ir uzbūvēta un saglabāta bināra koka veidā, kurā lapās atrodas simboli, bet uz lokiem ‘uzrakstīti’ cipari 0 vai 1. Simbola kods ir ceļš no koka saknes līdz šim simbolam. Izmantojot Hafmena adaptīvo kodēšanu paradās problēma, kura sastāv no pastāvīgas koka koriģēšanas sakarā ar ieejas plūsmas mainīgu statistiku.
Hafmena metodes priekšrocības ir viņas pietekami augsts ātrums un samazināšanas labā kvalitāte. Šīs algoritms jau sen ir zināms un plaši pielietots, piemēram tā ir programma Compress OS UNIX (programmas realizācija) un kodēšanas standarts faksiem (Hunter) (aparatūras realizācija).
Hafmena kodēšana ir minimāla pārpilnība nosacījumā, ja katrs simbols ir kodēts ar atsevišķu ķēdi alfabētā (simbola koda ķēde var saturēt tikai 0 un 1).
Hafmena metodes trūkums ir samazināšanas pakāpes sakarība no varbūtības simbolu tuvuma pie negatīviem divnieka pakāpēm, tas ir saistīts ar to, ka katrs simbols ir kodēts ar veselu bitu skaitu.
To mēs vislabāk varam redzēt situācijā, kad ir divsimbolu alfabēta kodēšana: šajā gadījumā samazināšanas vienmēr nav, neskatoties uz dažādu simbolu varbūtību; algoritms faktiski “noapaļo” tos līdz 1/2. Šī problēma varbūt dalīji atrisināta ieejas plūsmas bloķēšanas dēļ (t.i. ievads aplūkošanā jaunu simbolus, kuru veids ir ‘ab’, ‘abc’,… šeit a, b, c – sākotnēja alfabēta simboli). Tomēr, tas neļauj atbrīvoties no zaudējumiem pilnībā (tie tikai samazinās proporcionāli bloka izmēram) un palielina koda koka augstumu: ja, piemēram ieejas alfabēta simboli ir 8 bitu baiti ar vērtībām 0…255, tad kad mēs bloķējam pa diviem simboliem mēs ieguvām 65536 simbolus (koda koka lapas skaits ir 65536), bet kad mēs bloķējam pa trim – ieguvām 16777216. Atbilstoši pieaug prasības atmiņai un koka būvēšanas laiks (bet adaptīva kodēšanā – arī koka atjaunošanas laiks, tas nozīmē arī samazināšanas laiks). Zaudējumi ir vidēji 1/2 bita uz simbolu, gadījumā kad nav kodēšanas, bet kad kodēšana ir – 1/4 un 1/6 bita atbilstoši blokiem, kurš garums ir 2 un 3.

PRAKTISKĀ DAĻA

Uzdevuma nostādne

Šī programma ir utilītprogramma ar nosaukumu ‘Arhivator’. Tā būs paredzēta faila izmēru samazināšanai.
Izejot no teorētiskas daļas noteikumiem, mēs varam definēt prasības savai programmai:
1. programmai jānodrošina paziņojumu un pieprasījumu izvade ekrānā (lietotāja interfeisu).
2. programmai jānodrošina iespēju pieņemt parametrus no komandas rindas.
3. programmai jānodrošina lietotājam iespēju ievadīt faila nosaukumu un direktoriju.
4. programmai jākodē failu, pēc lietotāja izvēles:
4.1. jāskaita faila simbolu daudzums un katra simbola frekvence.
4.2. pareizi jāizveido kodu katram simbolam.
4.3. jāieraksta kodētā failā kodu tabulu.
4.4. jālasa pa simbolu no faila, jāatrada simbola kods, jāieraksta simbola kods kodētā failā.
5. programmai jāatjauno kodēta faila saturu:
5.1. jālasa no kodēta faila kodu tabulu.
5.2. jālasa no kodēta faila pa simbolu, jāatrada simbolu pēc koda kodu tabulā, jāieraksta failā simboli.

Programmas izveides gaitā arī jānodrošina šādas nefunkcionālās prasības:
1) CPU 80386 SX – 25 MHz.
2) RAM 1 Mb.
3) HDD 150 Kb.
4) OS DOS (Windows).

Izstrādājamai programmai ir jāveic dažādas darbības, kurus varam sadalīt pa trim lielākām grupām: interfeisu atbalstīšana, faila kodēšana, kodēta faila atjaunošana.
Savukārt mēs varam izdalīt no grupa ‘faila kodēšana’ šīs apakšgrupas:
 jāskaita faila simbolu daudzums un katra simbola frekvence.
 pareizi jāizveido kodu katram simbolam.
 jāieraksta kodētā failā kodu tabula.
 jālasa pa simbolu no faila, jāatrada simbola kods, jāraksta simbola kods kodētā failā.

No grupas ‘kodēta faila atjaunošana’ izdalīsim šādas operācijas:
 jālasa no kodēta faila kodu tabulu.
 jālasa no kodēta faila pa simbolu, jāatrada simbols pēc koda kodu tabulā, jāraksta atjaunotā failā simbols.

No grupās ‘interfeisu atbalstīšana’ izdalīsim šādas operācijas:
 jāatbalsta faila nosaukumu pieņemšana no komandas rindas un pamatojaties uz to paplašinājumu jāizvēlas vajadzīga operācija (kodēšana vai atjaunošana) bez direktoriju un faila nosaukumu ievadīšanas programmas izpildes laikā;
 pieprasījums ievadīt faila atradīšanas direktoriju;
 pieprasījums ievadīt faila nosaukumu;
 paziņojumu izvade ekrānā;
 programmas arhitektūra sastāv no 5 moduļiem:
 interfeisu atbalstīšana (mazas funkcijas, kuras atbalsta izvadi ekrānā, ka arī dažādus paskaidrojumus) (Modulis Arh_inte.pas);
 skaita simbolu daudzumu failā, skaita katra simbola atkārtojumu un izveido pagaidu failu ar nosaukumu ‘vit.tmp’ (Modulis Arh_coun.pas);
 izveido kodētu failu (Modulis Arh_cod.pas);
 atjauno kodētu failu (Modulis Arh_ucod.pas);
 nodrošina lietotājam iespēju izvēlēt kodēšanas vai atjaunošanas operāciju (Arh_main.pas);

Algoritma apraksts

Moduļa ‘Arh_main.pas’ algoritms

 Pārbaudam ja eksistē parametri no komandas rinda;
 Ja parametri eksistē:
 Pārejam uz faila eksistēšanu un paplašinājumu pārbaude;
 Ja parametri neeksistē:
 Pieprasam ievadīt faila atradīšanas direktoriju;
 Ja direktorija eksistē:
 Pieprasam ievadīt faila nosaukumu ar paplašinājumu;
 Ja fails eksistē:
 Pārbaudam faila paplašinājumu:
 Ja paplašinājums nav ‘vit’, tad izsaucam procedūru ‘coding’;
 Ja paplašinājums ir ‘vit’, tad izsaucam procedūru ‘uncoding’;
 Ja fails neeksistē šajā direktorijā izvadam paziņojumu, pār to, ka fails neeksistē;
 Ja direktorija neeksistē, tad izvadam paziņojumu, pār to, ka direktorija neeksistē;
 Darba beigšana;

Programmas apraksts

2.3.1. Lietojumsfēra

Programma ir paredzēta faila izmēra samazināšanai.
Programmēšanas valoda – TURBO PASCAL 7.0. Programma izpildīta ar Pentium 166 MMX datoru operātājsistēmas MS DOS vidē.
Programmas darbība ir pārbaudīta vairākus reizes, ievadot dažādus faila nosaukumus un failiem bija dažādi saturi, ka arī dažādi paplašinājumi.

2.3.2. Ievaddati

Direktorijas nosaukums, faila nosaukums, fails (jebkurš faila tips vai kodēts fails).

2.3.3. Izvaddati

Atjaunots fails vai kodēts fails, informācija pār darbības veikšanu un operācijas procentuālas izteiksmi.

2.3.4. Ziņas par programmas apjomu un izpildes laiku

Galvena programma: Arh_main.pas – 2323B

Moduli:
1. Arh_inte.pas – 3949B
Arh_inte.tpu – 4704B
2. Arh_coun.pas – 1228B
Arh_coun.tpu – 2064B
3. Arh_cod.pas – 5048B
Arh_cod.tpu – 6768B
4. Arh_ucod.pas – 3086B
Arh_ucod.tpu – 4240B
Izpildāmais fails Arh_main.exe – 19520B
Programmas izpildes laiks – atkarīgs no datora procesora, no cieta diska ātruma un no lietotāja (cik ātri viņš atbildīs uz programmas pieprasījumiem).

2.3.5. Moduļu apraksts

Programma sastāv no pieciem moduļiem (zīm. 1.).

.

Zīm. 1.

Moduli tiek glabāti dažādos failos (1.tab.). Programmas pirmteksts dots 1. pielikuma.

Moduļi un faili
Modulis Pirmteksta fails Objektfails
Arh_main
Arh_inte
Arh_cod
Arh_coun
Arh_ucod Arh_main.pas
Arh_inte.pas
Arh_cod.pas
Arh_coun.pas
Arh_ucod.pas
Arh_inte.tpu
Arh_cod.tpu
Arh_coun.tpu
Arh_ucod.tpu
1. tabula

Programmas atkļūdošanai un izpildei tiks izveidots izpildāms fails Arh_main.exe.

2.3.6. Procedūru un funkciju apraksts

Modulis ‘Arh_inte.pas’:
Procedure Cls – attīra ekrānu;
Procedure Curoron – ieslēdz kursoru;
Procedure Cursoroff – izslēdz kursoru;
Procedure Frame (X, Y, X1, Y1, Cvet, Bk, Till: integer) – zīme ekrānā logu;
Function Vvod (Chto: String; X, Y, X1, Y1, Kolvo_Simvolov: Integer; Chisla: Boolean): String – nolasa simbolus no tastatūras;
Procedure I_Reading (Percent: Integer) – izvada ekrānā logu un skaitļu;
Procedure Error (What: String) – izvada ekrānā paziņojumu pār kļūdu;

Modulis ‘Arh_cod.pas’:
Procedure Coding (File_Name, Exten: String) – izveido kodēto failu;
Function Len: Integer – Atgriež kodu garumu;

Modulis ‘Arh_coun.pas’
Procedure Counter (File_Name: String) – skaita simbolus tekstā failā, katra simbola atkārtojumu un ieraksta šīs datus failā ‘vit.tmp’;

Modulis ‘Arh_ucod.pas’
Procedure UnCoding (File_Name: String) – izveido teksta failu no kodēta faila;
Procedure Msearch – Atrod simbolu pēc koda un ieraksta simbolu tekstā failā;

LIETOTĀJA INSTRUKCIJA

Programmas izpilde notiek ar faila ‘Arh_main.exe’ palaišanu.
Mēs varam palaist programmu ar parametri un bez tam. Ja mēs palaižam to ar parametri mums ir jānorada faila nosaukums ar paplašinājumu un to pilnu ceļu. Tad jums nevajag ievadīt faila atrašanas direktoriju un to nosaukumu programmas izpildes gaitā.
Ja mēs palaižam programmu bez parametra. Pēc programmas palaišanas tiek atspoguļots logs, kurā jums ir jāievada faila atrašanas direktorija. Ja jūs ievadīsiet neeksistējošu direktoriju, tad programma, ekrānā lejā, izvadīs atbilstošu paziņojumu, pār to, ka direktorija neeksistē, pieprasīs jūs vai iziet no programmas, ja ne, tad atkal ievadam direktoriju, ja iziet, tad izejam no programmas. Pēc eksistējošas direktorijas ievadīšanas jums ir jāievada faila nosaukumu ar paplašinājumu. Ja fails eksistē un viņas paplašinājums ir nav ‘vit’, tad sākam kodēšanas procesu, ja paplašinājums ‘vit’, tad sākam atjaunošanas procesu. Programmas izpildes gaita ekrānā būs redzami dažādi paziņojumi un paskaidrojumi, jums tikai ir jāskatās ekrānā un jālasa izvadāma informācija. Pēc programmas beigas, ja bija izpildīta kodēšana vai atjaunošana, būs fails, kurš tiek izveidots kodēšanas vai atjaunošanas dēļ (fails glabājas direktorijā, kuru ievadīja lietotājs).

PROGRAMMAS FUNKCIONĒŠANAS KONTROLES PIEMĒRS

Programmas pārbaudei es kodēju un atjaunoju dažādus failus ar dažādiem paplašinājumiem un dažādiem izmēriem.
Testēšanās laikā kļūdas nebija redzami.

2. Zīm. Direktorijas ievade.
Šajā zīm. 2. tiek pāradīts direktorijas ievadīšanas process. Šeit lietotājs ievada neeksistējošo direktoriju un ekrānā lejā mēs redzam paziņojumu pār to. Tagad lietotājs var uzspiest taustiņu ESC un iziet no programmas vai nospiest jebkuru citu taustiņu un izlabot ceļu.

3. Zīm. Faila nosaukuma ievadīšana.
Šajā zīm. 3. šeit tiek paradīts faila nosaukuma ievadīšanas process. Šajā gadījumā mēs redzam, kā lietotājs ievada nepareizu faila nosaukumu. Atkal ekrānā lejā mēs redzam paskaidrojumu un lietotājs var iziet no programmas uzspiežot taustiņu ESC vai var izlabot ievadītu faila nosaukumu nospiežot jebkuru taustiņu.

4. Zīm. Darba beigšana.
Šajā zīmējuma tiek paradīta programmas pabeigšana ekrānā tiek izvadīts paziņojums par to, kāda ir samazināšanas gradē procentos (cik procentus sastāda kodēta faila izmērs no sākuma faila izmēru).

SECINĀJUMI

Kvalifikācijas darba izveidošanas gaitā bija izpildīts uzdevuma analīze, ka arī programmas prasības noteikšana. Pēc analizēšanas bija izstrādāts algoritms, kurš strādā pēc ‘Hafmana kodu’ principa tikai neizmanto binārus kokus.
Kvalifikācijas darba bija atrisināta programmēšanas valodā TURBO PASCAL 7.0. un izpildīta ar datora Pentium 166 MMX operētājsistēmā MS-DOS vidē. Visas kļūdas, kuri radojas darba izpildes gaitā bija uzlaboti, izstrādāta programma bija testēta vairākas reizes un kļūdas nebija vairāk redzētas.
Kvalifikācijas darbs bija ļoti sarežģīts. Tā izpildei bija nepieciešamas apmēram 58 stundas, no kurām 5 stundas aizņēma uzdevuma analīze, 20 stundas aizņēma programmas izveide, apmēram 18 stundas – pārskata noformēšana, palīkušas stundas es veltīju programmas testēšanai un kļūdu uzlabošanai.

IZMANTOTA LITERATŪRA

1. Керниган Б., Ритчи Д. Язык программирования PASCAL. – Москва, 1992.
2. Справочник по функциям TURBO PASCAL 7.0. 3.1-4.0. – Киев: Диалектика, 1994.- 416 с.
3. Witten, I.H., Neal, R.M., and Cleary, J.G. Arithmetic coding for data compression.
4. Commun. ACM 30, 6 (June 1987), 520-540. Классическая работа по арифметическому кодированию.
5. Кричевский, Р.Е. Сжатие и поиск информации. – М.: Радио и связь, 1989.

PIELIKUMS

PROGRAMMAS PIRMTEKSTS

Modulis ‘Arh_main’:

Program Arhivat_Main;

Uses CRT,Arh_Inte,Arh_Cod,Arh_UCod;

Label End_Prog;
Var Key:Char;
S_Direct:String[60];
Curr_Direct:String[255];
File_name:String[12];
Exten:String[3];
I:Integer;
Ok,Exit:Boolean;
F:File of Byte;

Begin
GetDir(0,Curr_Direct);
Cls;
IF ParamCount>0 Then
Begin
File_Name:=ParamStr(1);
Assign(F,File_name);
{$I-}
Reset(F);
{$I+}
IF (IOResult<>0) Then
Begin
Writeln(‘File not exist or incorect path!’);
Write(‘Press any key’);
IF Readkey=Chr(0) Then
Readkey;
Goto End_Prog;
End;
End
Else
Begin
Exit:=False;
Repeat
Cls;
Frame(9,11,71,14,White,Blue,14);
GotoXY(20,1);
Writeln(‘Enter source directory:’);
GotoXY(2,2);
Write(S_Direct);
S_Direct:=Vvod(S_Direct,10,13,70,13,60,False);
{$I-}
ChDir(S_Direct);
{$I+}
IF (IOResult<>0) Then
Begin
Ok:=False;
Cursoroff;
Error(‘path.’);
Key:=Readkey;
IF Key=Chr(0) Then
Readkey;
Cursoron;
IF (Key=Chr(27)) Then
Exit:=True;
End
Else
Ok:=True;
Until((OK) or (Exit));
Ok:=False;
While ((OK=False) and (Exit=False)) Do
Begin
Cls;
Frame(9,11,71,14,White,Blue,14);
GotoXY(19,1);
Writeln(‘Enter filename with extension:’);
GotoXY(2,2);
Write(File_Name);
File_Name:=Vvod(File_Name,10,13,70,13,12,False);
Assign(F,File_Name);
{$I-}
Reset(F);
{$I+}
IF (IOResult<>0) Then
Begin
Ok:=False;
Cursoroff;
Error(‘filename.’);
Key:=Readkey;
IF Key=Chr(0) Then
Readkey;
Cursoron;
IF (Key=Chr(27)) Then
Exit:=True;
End
Else
Ok:=True;
End;
End;
Cursoroff;
IF (Not Exit) Then
Begin
Close(F);
I:=1;
While ((I<=Length(File_Name)-3) and (File_Name[I]<>’.’)) Do
Inc(I);
IF (I<=Length(File_Name)-3) Then
Exten:=Copy(File_Name,I+1,3);
For I:=1 To Length(Exten) Do
Exten[i]:=UpCase(Exten[i]);
{Coding}
IF (Exten<>’VIT’) Then
Coding(File_Name,Exten)
Else
{UnCoding}
Uncoding(File_Name)
End;
End_Prog:
Cursoron;
Cls;
ChDir(Curr_Direct);
End.

Modulis ‘Arh_Coun’:

Unit Arh_Coun;
Interface
Uses Arh_Inte;
Procedure Counter(File_Name:String);
Implementation
Type PSymbol=^Symbol;
Symbol=Record
Symb:Byte;
Kol_vo:LongInt;
End;
Arr_Symb=Array[0..255] of PSymbol;

Procedure Counter(File_Name:String);
Var Mass:Arr_Symb;
F:File of Byte;
I,One_Percent:LongInt;
II:Integer;
F1:File of Symbol;
Temp:Byte;

Begin
For I:=0 To 255 Do
Mass[I]:=Nil;
Assign(F,File_Name+’exe’);
Reset(F);
Cls;
Frame(34,18,45,20,15,1,20);
Write(‘Reading…’);
I_Reading(0);
One_Percent:=Trunc(FileSize(F)/100);
For I:=1 To FileSize(F) Do
Begin
IF ((I mod One_percent)=0) Then
I_Reading(I div One_Percent);
Read(F,Temp);
II:=0;
While ((Mass[II]<>Nil) and (II<=255) and (Mass[II]^.Symb<>Temp)) Do
Inc(II);
IF Mass[II]=Nil Then
Begin
New(Mass[II]);
Mass[II]^.Symb:=Temp;
Mass[II]^.Kol_vo:=1;
End
Else
Inc(Mass[II]^.Kol_vo);
End;
Close(F);
Assign(F1,’vit.tmp’);
Rewrite(F1);
I:=0;
While ((Mass[I]<>Nil) and (I<=255)) Do
Begin
Write(F1,Mass[I]^);
Inc(I);
End;
Close(F1);
End;
End.

Modulis ‘Arh_Cod’:

Unit Arh_Cod;
Interface
Uses Arh_Coun,Arh_Inte,CRT;
Type PSymbol=^Symbol;
Symbol=Record
Symb:Byte;
Kol_vo:LongInt;
End;
Arr_Symb=Array[0..255] of PSymbol;

Procedure Coding(File_Name,Exten:String);
Implementation
Procedure Coding(File_Name,Exten:String);
Type PG_Symbol=^G_Symbol;
G_Symbol=Record
Gr_Symb:String[255];
Kolvo:LongInt;
Sym_Code:String[255];
End;
Arr_G_Symbol=Array[0..255] of PG_Symbol;
PStroka=^Stroka;
Stroka=String[255];

Var F:File of Symbol;
a,b:Byte;
Mass:Arr_Symb;
One_Percent,I,II,III:LongInt;
Posled:Array [0..255] of PStroka;
K,Kol_Sym:Integer;
Code_mass:Arr_G_Symbol;
PTemp:PG_Symbol;
Kolvo_Symb:Byte;
F1:File of byte;
F_cod:File of byte;

Function Len:Integer;
Begin
i:=0;
While (Code_mass[i]^.Gr_Symb<>chr(a)) Do
inc(i);
Len:=Length(Code_mass[i]^.Sym_code);
End;

Begin
Cls;
Counter(File_Name);
Assign(F,’vit.tmp’);
Reset(F);
Kol_Sym:=0;
I:=0;
Cls;
Frame(30,18,50,20,15,1,20);
Write(‘Generating codes…’);
While (Kol_Sym<Filesize(F)) Do
Begin
New(Mass[Kol_Sym]);
Read(F,Mass[Kol_Sym]^);
Inc(Kol_Sym);
End;
Close(F);
Erase(F);
Kolvo_Symb:=Kol_Sym-1;
II:=0;
While (II<=Kolvo_Symb) Do
Begin
New(Code_mass[II]);
Code_mass[II]^.Gr_Symb:=Char(Mass[II]^.Symb);
Code_mass[II]^.Kolvo:=Mass[II]^.Kol_vo;
Dispose(Mass[II]);
Inc(II);
End;
For I:=0 To Kolvo_Symb-1 Do
For II:=I+1 To Kolvo_Symb Do
IF (Code_mass[II]^.Kolvo>Code_Mass[I]^.Kolvo) Then
Begin
PTemp:=Code_mass[I];
Code_mass[I]:=Code_mass[II];
Code_mass[II]:=PTemp;
End;
k:=-1;
For Kolvo_Symb:=Kolvo_Symb Downto 2 Do
Begin
Code_mass[Kolvo_Symb-1]^.Kolvo:=Code_mass[Kolvo_Symb-1]^.Kolvo+Code_mass[Kolvo_Symb]^.Kolvo;
Code_mass[Kolvo_Symb-1]^.Gr_Symb:=Code_mass[Kolvo_Symb-1]^.Gr_Symb+Code_mass[Kolvo_Symb]^.Gr_Symb;
Inc(K);
New(Posled[K]);
Posled[K]^:=Code_mass[Kolvo_Symb]^.Gr_Symb;
Dispose(Code_mass[Kolvo_Symb]);
Code_mass[Kolvo_Symb]:=Nil;
For I:=0 To Kolvo_Symb-1 Do
For II:=I+1 To Kolvo_Symb Do
IF (Code_mass[II]^.Kolvo>Code_Mass[I]^.Kolvo) Then
Begin
PTemp:=Code_mass[I];
Code_mass[I]:=Code_mass[II];
Code_mass[II]:=PTemp;
End;
End;
Code_mass[0]^.Sym_Code:=’1′;
Code_mass[1]^.Sym_Code:=’0′;
While (K>-1) Do
Begin
I:=0;
While (Code_mass[I]^.Gr_Symb[length(Code_mass[I]^.Gr_Symb)]<>Posled[K]^[Length(Posled[K]^)]) and (K>-1) Do
Inc(I);
IF (k>-1) Then
Begin
II:=1;
While (Code_mass[II]<>Nil) Do
Inc(II);
New(Code_mass[II]);
Code_mass[II]^.Sym_Code:=Code_mass[I]^.Sym_Code+’0′;
Code_mass[I]^.Sym_Code:=Code_mass[I]^.Sym_Code+’1′;
Code_mass[II]^.Gr_Symb:=copy(Code_mass[I]^.Gr_Symb,Length(Code_mass[I]^.Gr_Symb)-Length(Posled[K]^)+1,Length(Posled[K]^));
Delete(Code_mass[I]^.Gr_Symb,Length(Code_mass[I]^.Gr_Symb)-Length(Posled[K]^)+1,Length(Posled[K]^));
Dispose(Posled[K]);
Dec(K);
Code_mass[II]^.Kolvo:=0;
End;
End;
Delete(File_Name,Length(File_Name)-2,3);
Assign(F_cod,(File_Name+’vit’));
Rewrite(F_cod);
Kolvo_Symb:=Kol_Sym-1;
a:=ord(Exten[1]);
Write(F_cod,a);
a:=ord(Exten[2]);
Write(F_cod,a);
a:=ord(Exten[3]);
Write(F_cod,a);
Write(F_cod,Kolvo_Symb);
For I:=0 To Kol_Sym-1 Do
Begin
a:=ord(Code_mass[I]^.Gr_Symb[1]);
Write(F_cod,a);
a:=length(Code_mass[I]^.Sym_code);
Write(F_cod,a);
k:=0;
a:=0;
For II:=1 To length(Code_mass[I]^.Sym_Code) Do
Begin
a:=a shl 1;
IF Code_mass[I]^.Sym_Code[II]=’1′ Then
a:=a+1;
Inc(k);
IF (k=8) Then
Begin
Write(F_cod,a);
a:=0;
k:=0;
End;
End;
IF (K<>0) Then
Write(F_cod,a);
End;
Assign(F1,File_Name+Exten);
Reset(F1);
k:=0;
b:=0;
Cls;
Frame(30,18,50,20,15,1,20);
Write(‘Creating archive…’);
I_Reading(0);
One_Percent:=Trunc(FileSize(F1)/100);
For III:=1 To FileSize(F1) Do
Begin
IF ((III mod One_percent)=0) Then
I_Reading(III div One_Percent);
Read(F1,a);
For II:=1 To len Do
Begin
b:=b shl 1;
IF Code_mass[I]^.Sym_Code[II]=’1′ Then
b:=b+1;
Inc(k);
IF (k=8) Then
Begin
Write(F_cod,b);
b:=0;
k:=0;
End;
End;
End;
Write(F_cod,b);
Write(F_cod,byte(k));
Cls;
Close(F_cod);
Assign(F_cod,(File_Name+’vit’));
Reset(F_cod);
Frame(28,10,52,12,WHITE,BLUE,12);
Write(‘Compression ratio = ‘,(Filesize(F_cod)*100) div (FileSize(F1)),’%’);
Frame(33,15,47,17,WHITE,BLUE,17);
Write(‘Press any key’);
IF Readkey=Chr(0) Then
Readkey;
Close(F1);
Close(F_cod);
End;
End.

Modulis ‘Arh_ucod’:

Unit Arh_UCod;
Interface
Uses Arh_Inte,CRT;
Procedure Uncoding(File_Name:String);
Implementation
Procedure Uncoding(File_Name:String);
Type PSym_Code=^Sym_Code;
Sym_Code=Record
Symbol:Char;
S_Code:String[255];
End;
Var F:File of Byte;
F1:File of Char;
II,I:Integer;
Tek_Symb,One_Percent:LongInt;
T,Tmps:String[255];
Cod,Temp,Kolvo_Symb:Byte;
Code_mass:Array [0..255] of PSym_Code;

Procedure MSearch;
Var k,j:Integer;
TempStr:String;
Begin
k:=0;
TempStr:=T[1];
j:=1;
While (J<=Length(T)) Do
Begin
k:=0;
While ((Code_mass[k]^.S_Code<>TempStr) and (k<=Kolvo_Symb)) Do
inc(K);
IF (Code_mass[k]^.S_Code=TempStr) Then
Begin
Write(F1,Code_mass[K]^.Symbol);
Delete(T,1,Length(TempStr));
Delete(TempStr,1,255);
TempStr:=T[1];
j:=1;
End
Else
Begin
Inc(J);
TempStr:=TempStr+T[J];
End;
End;
End;

Begin
Cls;
Frame(34,12,46,14,White,Blue,14);
GotoXY(2,1);
Write(‘Uncoding…’);
Delete(File_Name,Length(File_Name)-2,3);
Assign(F,File_Name+’vit’);
Reset(F);
Delete(Tmps,1,255);
Read(F,Temp);
Tmps:=Tmps+chr(Temp);
Read(F,Temp);
Tmps:=Tmps+chr(Temp);
Read(F,Temp);
Tmps:=Tmps+chr(Temp);
Assign(F1,File_Name+Tmps);
Rewrite(F1);
I_Reading(0);
One_Percent:=Trunc(FileSize(F)/100);
Tek_Symb:=3;
Read(F,Kolvo_Symb);
Inc(Tek_Symb);
For I:=0 To Kolvo_Symb Do
Begin
New(Code_mass[I]);
Read(F,Temp);
Inc(Tek_Symb);
Code_mass[I]^.Symbol:=Chr(Temp);
Read(F,Temp);
Inc(Tek_Symb);
Code_mass[I]^.S_Code:=”;
While (Temp<>0) Do
Begin
Read(F,Cod);
Inc(Tek_Symb);
T:=’qwertyui’;
For II:=1 To 8 Do
Begin
IF (Cod>127) Then
T[II]:=’1′
Else
T[II]:=’0′;
Cod:=Cod Shl 1;
End;
IF (Temp>=8) Then
Begin
Code_mass[I]^.S_Code:=Code_mass[I]^.S_Code+T;
Temp:=Temp-8;
End
Else
Begin
Code_mass[I]^.S_Code:=Code_mass[I]^.S_Code+copy(T,Length(T)-(Temp-1),Temp);
Temp:=0;
End;
End;
End;
T:=”;
Read(F,Temp);
Inc(Tek_Symb);
While (Not EOF(F)) Do
Begin
IF ((Tek_Symb mod One_percent)=0) Then
I_Reading(Tek_Symb div One_Percent);
Cod:=Temp;
Read(F,Temp);
Inc(Tek_Symb);
IF (Not EOF(F)) Then
Begin
Tmps:=’qwertyui’;
For II:=1 To 8 Do
Begin
IF (Cod>127) Then
Tmps[II]:=’1′
Else
Tmps[II]:=’0′;
Cod:=Cod Shl 1;
End;
T:=T+Tmps;
Msearch;
End;
End;
IF Temp>0 Then
Begin
Tmps:=’qwertyui’;
For II:=1 To 8 Do
Begin
IF (Cod>127) Then
Tmps[II]:=’1′
Else
Tmps[II]:=’0′;
Cod:=Cod Shl 1;
End;
Delete(Tmps,1,Length(Tmps)-Temp);
T:=T+Tmps;
MSearch;
End;
Close(F);
Close(F1);
End;
End.
Modulis ‘Arh_inte’:

Unit Arh_Inte;
Interface
Procedure Cls;
procedure cursoron;
procedure cursoroff;
Procedure Frame(X,Y,X1,Y1,Cvet,Bk,Till:Integer);
Function Vvod(Chto:String;X,Y,X1,Y1,Kolvo_Simvolov:Integer;Chisla:Boolean):String;
Procedure Error(What:String);
Procedure I_Reading(Percent:Integer);
Implementation
Uses Crt;
Procedure Cls;
Begin
TextBackGround(Black);
Window(1,1,80,25);
ClrScr;
End;

Procedure Cursoron;
Begin
asm
mov ax,$0100;
mov cx,$1F1f;
int 10h;
end;
End;

procedure cursoroff;
begin
asm
mov AX,$0100;
mov cx,$2020;
int 10h;
end;
end;

Procedure Frame(X,Y,X1,Y1,Cvet,Bk,Till:Integer);
Var I:Integer;
Begin
Window(X,Y,X1,Till);
TextColor(Cvet);
TextBackGround(Bk);
ClrScr;
Window(X,Y,X1,Till+1);
GotoXY(X1-X+1,Till-Y+1);
Write(‘ј’);
GotoXY(1,1);
Write(‘Й’);
For I:=2 To X1-X Do
Write(‘Н’);
Write(‘»’);
For I:=2 To Till-Y Do
Begin
GotoXY(1,I);
Write(‘є’);
End;
GotoXY(1,Till-Y+1);
Write(‘И’);
For I:=2 To X1-X Do
Write(‘Н’);
For I:=2 To Till-Y Do
Begin
GotoXY(X1-X+1,I);
Write(‘є’);
End;
Window(X,Y+1,X1,Y1);
GotoXY(2,1);
End;

Function Vvod(Chto:String;X,Y,X1,Y1,Kolvo_Simvolov:Integer;Chisla:Boolean):String;
Var Klavisha:Char;
Temp_Str:String;
I,Pozition:Integer;
Plus:String[1];
Vvod_Chisla:Set Of Char;
Begin
Vvod_Chisla:=[‘0′..’9′,’,’,’.’];
Window(X,Y,X1,Y1);
Temp_Str:=Chto;
Klavisha:=’ ‘;
Pozition:=1;
While Klavisha<>Chr(13) Do
Begin
Klavisha:=Readkey;
IF ((Klavisha<>Chr(13)) and (Klavisha<>Chr(8)) and (Klavisha<>Chr(0)) and (Klavisha<>Chr(27)) and (Klavisha<>Chr(9))) Then
IF ((Chisla=False) and (Kolvo_Simvolov>Length(Temp_Str))) Then
Begin
Plus:=Klavisha;
Insert(Plus,Temp_Str,Pozition);
GotoXY(Pozition,1);
For I:=Pozition To Length(Temp_Str) Do
Write(Temp_Str[I]);
Inc(Pozition);
GotoXY(Pozition,1);
End
Else
IF ((Klavisha in Vvod_Chisla) and (Kolvo_Simvolov>Length(Temp_Str))) Then
Begin
Plus:=Klavisha;
Insert(Plus,Temp_Str,Pozition);
GotoXY(Pozition,1);
For I:=Pozition To Length(Temp_Str) Do
Write(Temp_Str[I]);
Inc(Pozition);
GotoXY(Pozition,1);
End;
IF ((Klavisha=Chr(8)) and (Pozition>1)) Then
Begin
Dec(Pozition);
Delete(Temp_Str,Pozition,1);
GotoXY(Pozition,1);
For I:=Pozition To Length(Temp_Str) Do
Write(Temp_Str[I]);
Write(‘ ‘);
GotoXY(Pozition,1);
End;
IF Klavisha=Chr(0) Then
Begin
Klavisha:=ReadKey;
IF Klavisha=Chr(75) Then
IF Pozition>1 Then
Begin
Dec(Pozition);
GotoXY(Pozition,1);
End;
IF Klavisha=Chr(77) Then
IF Pozition<Length(Temp_Str)+1 Then
Begin
Inc(Pozition);
GotoXY(Pozition,1);
End;
IF Klavisha=Chr(79) Then
Begin
Pozition:=Length(Temp_Str)+1;
GotoXY(Pozition,1);
End;
IF Klavisha=Chr(71) Then
Begin
Pozition:=1;
GotoXY(Pozition,1);
End;
IF (Klavisha=Chr(83)) and (Length(Temp_Str)>0) Then
Begin
Delete(Temp_Str,Pozition,1);
For I:=Pozition To Length(Temp_Str) Do
Write(Temp_Str[I]);
Write(‘ ‘);
GotoXY(Pozition,1);
End;
End;
End;
Vvod:=Temp_Str;
End;

Procedure Error(What:String);
Begin
Frame(18,21,61,24,White,Blue,24);
Write(‘You have entered incorrect ‘,What);
GotoXY(2,2);
Write(‘Press (ESC) to Exit or any key to Continue’);
End;

Procedure I_Reading(Percent:Integer);
Begin
Frame(38,22,42,24,White,Blue,24);
Write(Percent,’%’);
End;
End.