Autors: V. Tolmačevs
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.
1. TEORETISKĀ DAĻA
1.1. 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.
1.2. 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.
1.3. 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.
2. PRAKTISKĀ DAĻA
2.1. 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);
2.2. 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;
2.3. 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ā;
3. 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).
4. 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).
5. 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.
6. 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.
7. 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
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
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.
Nav komentāru:
Ierakstīt komentāru