• AMOS - Oszczędzamy miejsce na dysku

29.06.2010 20:32, autor artykułu: Michał "Qualis" Speier
odsłon: 2929, powiększ obrazki, wersja do wydruku,

Poniższy artykuł powstał wiele lat temu z intencją publikacji w "Magazynie Amiga". Nie pamiętam już, czy w końcu go wysłałem do redakcji, czy też nie. Zapewne to pierwsze, a redakcja uznała rzecz za mało godną uwagi. Czy dziś, współcześnie, proponowane rozwiązanie może komuś się przydać? Być może. Retro jest wszak modne, programowanie w "wyklętym" Amosie proste i przyjemne (ah, niechaj zatem ten, komu podoba się Python pierwszy rzuci kamieniem w nas, amosowców...!), a jak ktoś potrzebuje akurat umieścić większą ilość danych na dysku... Oto gotowe rozwiązanie. Oryginalny tekst prezentuję właściwie bez zmian, tylko z drobnymi, kosmetyczno-historycznymi poprawkami.

Dawno, dawno temu, gdy wszyscy byli młodzi, a jabłka zawsze kwaśne i zielone, w "Magazynie Amiga" numer 12/96 ukazał się artykuł Łukasza Szeląga pt. "Oszczędzanie miejsca na dyskietkach". Dotyczył on genialnego pomysłu - łączenia wielu małych pliczków w jeden, za to duży plik. Zalety takiego rozwiązania? Głównie, by tak rzec z perspektywy czasu, historyczne... Przede wszystkim oszczędzanie miejsca na dysku, szybszy dostęp do danych (głównie na dyskietkach). Zapewne w dobie dzisiejszych wielkich dysków twardych, uzyskana oszczędność miejsca, jak i czas dostępu, jest niewielka, za to estetyka rozwiązania niewątpliwie lepsza. Zamiast mnóstwa plików - jeden duży. Niestety Łukasz podał rozwiązanie w snobistycznym "c" (wymawia się to jak sepleniące "ś", dziwne nie?). Chciałbym przedstawić to od strony Amosa. Rzecz jest bardzo prosta do wykonania.

Czas na przykład. Załóżmy, iż mamy 100000 pliczków z danymi (np. tekstem programujemy własny zin, co jest bardzo miłe, ponieważ pozwala na bezpośrednie głoszenie swoich poglądów na różne tematy), nasze pliki są bardzo małe, a jednak taka ilość może nie wejść na dyskietkę. Każdy wpis do katalogu dysku zabiera nam kawałeczek pojemności, poza tym, to o czym mowa była wcześniej - czas dostępu!

Zatem, 100000 plików o nazwie "tekst" plus jego numer (np. tekst1, tekst2 aż do tekst100000). Oczywiście mogą one mieć różne nazwy, lecz w takim wypadku nie da się zautomatyzować czynności łączenia ich w jeden duży plik.

Pierwsza procedura może być taka:

Procedure JOIN[SKAD$,NE$,ILE]
' SKAD$ - urządzenie bądź katalog, gdzie są nasze pliki przeznaczone do łączenia, np. "ram:" albo "Work:amos/zin/luty/artykuly"
' NE$ - nazwa bazowa plików np. "tekst"
' ILE - ile tego jest, np. 1000000

For A=1 To ILE : Rem - liczba plików
A$=Right$(Str$(A),Len(Str$(A))-1) : Rem usuwa spacje sprzed liczby
If Exist(SKAD$+NE$+A$) : Rem dla bezpieczeństwa, sprawdza czy plik jest.
Print At(0,0),"Pracuje nad - ";NE$+A$;"             "  : Rem ot, bajer...
Load SKAD$+NE$+A$,3 
XSAVE[NE$,A,3]  : Rem Bardzo Ważna procedura!
Erase 3 
End If 
Next A
End Proc

To tylko przykład. Dla uproszczenia przyjąłem, iż dane są już w formacie banku Amosa (komenda "Load" akceptuje tylko takie). Jeżeli tak nie jest, należy skorzystać z innych instrukcji (np. "Open" i "Input#", bądź "Sload", "Bload") tak, aby "zwykłe, nieamosowe" dane wrzucić do banku Amosa. Procedura robi właściwie jedną rzecz - wczytuje do pamięci kolejne pliki ("tekst1", "tekst2" itp. - po to one mają jedną nazwą bazową, aby komputer za nas wszystko robił), a następnie wywołuje główną procedurę:

Procedure XSAVE[X$,NR,BANK]
' X$ - nazwa naszego pliku, który chcemy nagrać
' NR - jego numer
' BANK - gdzie on jest (w jakim banku)

AD=Start(BANK)
A$=Right$(Str$(NR),Len(Str$(NR))-1)
If Length(AD)<>0
Append 1,"Ram:Indeks"+".xbf" : Rem dołączamy dane do pliku indeksu
Append 2,"Ram:Baza" : Rem dołączamy dane do pliku bazy
POZ=Pof(2) 
PLEN=Length(AD) 
Print #1,X$+A$+"$"+Right$(Str$(POZ),Len(Str$(POZ))-1)+"!"+Right$(Str$(PLEN),Len(Str$(PLEN))-1)+"&" 
Ssave 2,Start(AD) To Start(AD)+Length(AD) 
Close 1 : Close 2 : Rem tylko dla przykładu!
 End If 
End Proc

Mała uwaga - oba rozkazy "Close" powinny być oczywiście poza tą procedurą, bo powodują one za każdym razem "zamknięcie" pliku. A to należy uczynić dopiero pod koniec całej operacji. W wyniku tej procedury otrzymujemy dwa twory na dysku: jeden to plik indeksowy (z końcówką.xbf) a drugi (ten duży) to baza danych zawierająca wszystkie małe pliczki. Plik indeksowy jest zwykłym plikiem tekstowym i wygląda tak:

tekst1$0!23832&
tekst2$12!3984934&
tekst3$459!487&
i tak aż do:
tekst100000$383102439!340430585543&

Gdzie "tekst1" to nazwa pliku, potem jego pozycja (w pliku bazy jego początek liczony jest od początku tego pliku) oraz długość. Znaki "$", "!" i "&" są na użytek procedury, która odczytuje małe pliki z dużego. Musi ona wszak znać położenie każdego małego pliku umieszczonego w dużym (bazowym).

Komenda "Print#" dogrywa kolejną linę do pliku indeksowego, a komenda "Ssave" dane do pliku bazy. Polecenie "Append" jest właśnie po to, aby dogrywać do końca istniejącego już pliku nowe dane.

A skąd dokładnie wiemy gdzie w dużym pliku jest jakiś konkretny mały plik? Dobre pytanie. Odczytujemy poleceniem "Pof" miejsce, gdzie "Append" dołącza dane. Teraz, aby odczytać je z powrotem, musimy dodać do tego długość pliku, który nas interesuje. Wszystko to mamy już zapisane w indeksie. Jak go użyć (i jak wczytać) taki plik? Można tak:

Procedure XINIT[NE$]
Open In 1,NE$+".xbf" 
Reserve As Data 6000,Lof(1) 
Close 1 
Bload NE$+".xbf",Start(6000)
End Proc

Numer banku jest obojętny. Mając indeks w pamięci, jesteśmy gotowi do głównego "dania" - odczytania danych z pliku bazowego. Oto propozycja procedury odczytującej.

Procedure XLOAD[X$,NR]
' X$ - nazwa pliku, który chcemy odczytać
' NR - jego numer

A$=Right$(Str$(NR),Len(Str$(NR))-1)
NE$="Ram:Baza" : Rem nazwa pliku bazy

' Wcześniej należy załadować plik indeksowy do banku Amosa
' Tutaj jest on w banku numer 60000 (procedura XINIT)

XS=Start(6000) : XL=XS+Length(6000) 

AD=100 : Rem AD to numer banku, gdzie chcemy umieścić rozpakowany plik

' Oczywiście można rozpakować za jednym zamachem wiele plików, trzeba tylko dodać jedną linijkę:
' AD=100+NR
' Nowe pliki będą umieszczane sukcesywnie jeden za drugim.

ARK=Hunt(XS To XL,X$+A$+"$") : Rem szukamy konkretnego pliku!

' np. "tekst1"
' Można szukać wedle nazwy pliku wraz z jego numerem, po to właśnie jest zmienna "X$"
' Zmienna "ARK" podaje nam adres, pod którym znaleziono dany tekst (konkretną nazwę pliku np. "tekst666")
' teraz wystarczy odczytać pozycję i długość:

POZ=Val(Peek$(ARK+Len(A$)+2,999999,"!")) : Rem pozycja
PLEN=Val(Peek$(ARK+Len(Str$(POZ))+Len(A$)+2,999999,"&")) : Rem długość

Reserve As Data AD,PLEN : Rem rezerwujemy nowy bank dla naszych danych
 Open In 1,NE$ 
 Pof(1)=POZ : Rem ustawiamy głowicę dysku na początek danych
 Sload 1 To Start(AD),PLEN  : Rem i odczytujemy tyle ile nam potrzeba...
 Close 1
End Proc

W wyniku działania tej procedury mamy we wskazanym banku nasz mały pliczek. Możemy odczytywać za jej pomocą pojedyncze pliki (do wskazanego banku, trzeba tylko dodać nową zmienną, która by przekazywała procedurze "Xload" numer banku), jak i dowolną ich ilość (w pętli albo dodać jeszcze jedną zmienną mówiącą ile małych plików chcemy odczytać za jednym uruchomieniem procedury).

Zasada zostaje ta sama - odczyt danych z dużego pliku za pomocą danych z pliku indeksowego. Najwygodniej umieścić go sobie w pamięci, aby nie wczytywać go za każdym razem (oszczędność czasu!). Dalej, można dodać rozpoznawanie czy wczytujemy bank danych, rysunek czy moduł – ponieważ nie da się tak bezpośrednio wczytać modułu czy obrazka. Najlepiej (i ten sposób wykorzystałem pisząc grę "Ciemna Strona"), spakować wcześniej rysunki i moduły muzyczne - są one wtedy w postaci banku Amosa (komendy "squash" i "unsquash" - mogą być też użyte rozszerzenia programowe Amosa umożliwiające obsługę Xpk czy Crunchmanii) i nie ma problemów z ich wczytaniem (potem oczywiście się je rozpakowuje). Zysk podwójny - nasze dane są spakowane i umieszczone w jednym dużym pliku.

    
dodaj komentarz
Na stronie www.PPA.pl, podobnie jak na wielu innych stronach internetowych, wykorzystywane są tzw. cookies (ciasteczka). Służą ona m.in. do tego, aby zalogować się na swoje konto, czy brać udział w ankietach. Ze względu na nowe regulacje prawne jesteśmy zobowiązani do poinformowania Cię o tym w wyraźniejszy niż dotychczas sposób. Dalsze korzystanie z naszej strony bez zmiany ustawień przeglądarki internetowej będzie oznaczać, że zgadzasz się na ich wykorzystywanie.
OK, rozumiem