1541'i Anlamak (8)

Bu ayki konumuz, sıralı dosyalama olarak tercüme edebileceğimiz sequential filing tekniği. Haydi başlayalım... Disketimizi sadece programlarımızı SAVE etmek için kullanmamız gerekmiyor. Daha önceki bölümlerimizde de gördüğünüz gibi, PRG dışında REL, SEQ, DEL veya USR türü dosyalar da var. Bunlardan DEL önemsiz, çünkü sadece programın disketten silindiğini ama gene de directory'de durduğunu gösteriyor. USR ise, özellikle iş programları başta olmak üzere, profesyonel programların kendi veri dosyalarına verdikleri bir tip. Bizim için önemli olanlar SEQ türündeki sequential dosyalar ile REL türündeki relative dosyalar. Relative (göreceli) dosyalama tekniği gelecek konumuz. Şimdi sequential tekniğin üstüne üstüne gideceğiz... Dosyalama teknikleri arasında en hızlısı olmamakla birlikte en basiti sequential olanıdır. Çünkü bilgiler arka arkaya yığılmıştır. Her şey bilgilerin kaydedildiği sıraya göre yapılır. Daha önceleri kaset ünitesinde adreslerini saklamak isteyen arkadaşlar ne dediğimizi iyi anlıyor olmalılar. Genelde sequential dosyanın kullanıldığı adımlarda olur:

1) Dosyanın tamamı hafızaya yüklenir. 2) Gerekli değişiklikler yapılır. 3) Eski dosya silinir. 4) Yerine hafızadaki yeni bilgiler yazılır.

Gerçi 1541 bize bazı kolaylıklar sağlamıştır ama gene de genel yaklaşım budur. Tabii bu algoritma, eğer varolan bilgilerin ortasında bir yerde değişiklik yapılacaksa geçerli. Bu durumda ya dosya bilgisayarın belleğine sığacak kadar küçük olmalı (veya bilgisayarın belleği dosyayı alacak kadar büyük olmalı!), ya da yardımcı dosyalar kullanarak bu işlemleri halletmeliyiz. Eğer sadece sequential bir dosyadaki belli bir kaydı arayacaksak veya varolan bir dosyanın arkasına yeni bilgiler ekleyeceksek (arkasına, arasına değil!) tüm dosyayı bilgisayarın hafızasına geçirmemiz gerekmez. Bir dosya, ister sequential olsun isterse relative, kayıtlardan oluşur. Her bir kayıt da daha küçük alanlardan oluşur. Örneğin bir adres dosyasını ele alalım. Tüm adresler bir dosya oluşturur. Dolayısıyla, her adres bir kayıttır. Adresin isim, soyadı, adres, telefon gibi birimleri de alanları oluşturur. Dosyalamanın temelinde tüm kayıtların, dolayısıyla da alanların arka arkaya kaydedilmesi yatar. Ancak her kaydın hangi adreste başladığı (yani track/sector/byte) belli değildir. Onikinci kayda ulaşabilmek için baştan başlayıp ilk oniki kaydın okunması zorunludur. Zaten bu tür dosyaların sıkıntısı da budur. Eğer dosyamızda 1000 adres varsa ve biz en sonuncuyu istemişsek, o kayda ulaşıncaya kadar dakikalar geçecektir. Önce nasıl sequential dosya yaratıldığını görelim. Daha önce OPEN komutunu incelerken parametrelerini açıklamıştık. Bir özetleyelim:

OPEN dn,8,ia,“dosya,tür,mod”
(dn:dosya numarası, (a:ikincil adres)

Dosya numarası 1-127 arasında olacaktır. Yeter de artar bile. İkincil adres ise 2-14 arasında olabilir. 0 ve 1 okuma işlemleri tarafından, 15 ise komut ve hata kanalı tarafından kullanılır. Eğer birden fazla dosya aynı anda açık olacaksa, hem dosya numaraları hem de ikincil adresleri farklı olmalıdır. Bildiğiniz gibi 1541, her ikincil adres için bir buffer ayırıyor. Hatırlamıyorsanız son konumuzu bir kez daha gözden geçirin. Genellikle gözardı edilen bir gerçek var. Bu da aynı anda 1541'in en fazla üç dosyayı açık tutabileceği. Hatta relative dosya da kullanılıyorsa, bu dosyaların iki kanala birden ihtiyaç duyduklarını gözönüne alarak, sadece iki dosyanın aynı anda açık olabileceğini söyleyebiliriz. Yani aynı anda ya 3 sequential ya da 1 sequential

1 dosya açık olabilir. İki relative dosya açık olamaz. Dosya adının 16 karakterlik bir isim olacağını biliyorsunuz. Dosya türü yerine de S, U, P, R harflerinden biri gelmeli. Biz sequential dosya kullanacağımız için S harfini koyacağız. Mod ile de, dosyanın ne amaçla açıldığını belirliyoruz. W (write, yazma), R (read, okuma), A (append, ekleme) ile mod belirtilir. Bir de M modu vardır ki, bu mod ile daha önce açılmış ve doğru kapatılmamış, dolayısıyla da diğer modlarda okunamayan dosyaların okunması mümkün olur. Buna daha sonra geleceğiz. Örneğin OPEN 1,8,2, "DENEME,S,W" ile yazmak için DENEME adı altında bir sequential dosya yaratırız. Bu dosyalara yazma işleminin de PRINT ile yapıldığını biliyoruz. Hadi bir örnek yapalım...

10 OPEN 1,8,2,“DENEME,S,W”
20 PRİNT #1,“TUNA”
30 #1,“ERTEMALP”
40 PRİNT #1, “AYHAN”
50 PRİNT 81, “KALAYLIOĞLU”
60 PRİNT #1,“ZİYA”
70 PRİNT $1,“BAYMAN”
80 PRİNT #1,“TURHAN”
90 PRİNT #1, “TANDOĞMUŞ”
100 CLOSE 1

Gördüğünüz gibi, DENEME adı altında bir dosya açtık ve içine sekiz değişik bilgi yazdık. Bunların her birini bir bilgi alanı, isim ve soyadını bir kayıt, DENEME'yi de dosya olarak görebiliriz. Eğer DISKMON kolayda ise, bu dosyanın içeriğine bir göz atın. Her bilgi alanının arasında (örneğin TUNA ile ERTEMALP arasında ve ERTEMALP ile AYHAN arasında) $0D, yani RETURN karakter kodunu göreceksiniz. Eğer 20-90 arası satırların her birinin sonunda noktalı virgül olsaydı bunlar olmayacaktı. Ancak bu 13 değerini taşıyan byte'lar bilgi birimlerini birbirinden ayıran tahta perdelerdir. Onlar olmasaydı, dosyaladığımız bilgileri tekrar okumamız ve özellikle okuduklarımızı tekrar ilk yazıldıkları şekilde parçalara bölmemiz çok zor olurdu. Eğer bu programı çalıştırırken kullandığınız disketin üzerinde türü ne olursa olsun, adı DENEME olan bir başka dosya önceden varsa, kırmızı ışık yanıp sönecek ve PRINT # komutları bir işe yaramayacaktır. Bu durumda ya eski dosyayı silin, ya da DENEME yerine başka bir ad kullanın. Şimdi de bu dosyayı tekrar okuyalım... Okuma işlemi INPUT # ile olacaktır. Ancak INPUT #'un sadece 88 karakterlik bilgileri okuyabildiğini hatırlayalım. Eğer yukarıdaki programda aşağıdaki gibi bir ekleme olsaydı, daha ilk kaydı okumaya kalkıştığımızda hata oluşacaktı!

12 FOR 1-1 TO 100
13 PRİNT
14
15 PRİNT #1

Bu değişiklik ile, aralarında başka byte bulunmayan 100 adet arka arkaya yazıyoruz. Sonra da bu 100 byte'lık bilgiyi TUNA'dan ayırmak için 15. satırda boş bir PRINT#1 gönderiyoruz. Bu, bize istediğimiz $0D byte'ını yaratacaktır. Bir başka sorun da, bizim çok normal olduğunu düşünerek virgül ve iki nokta üstüste gibi karakterleri bir bilgi biriminin içinde kullanmamız olacaktır. Örneğin;

20 PRİNT “İSİM:TUNA,
ERTEMALP”

gibi bir satır olsaydı, INPUT # komutu bunu üç defada okuyabilecekti. Önce İSİM ilk bilgi birimi olarak karşımıza çıkacaktı. Sonra da TUNA ve ERTEMALP. Demek ki, “,” ve “:” karakterleri de $0D byte'ı ile aynı işi görüyorlar. Şimdi deminki programımızın ilk halini kabul edip yaratılan dosyayı INPUT okuduğumuza bir bakalım.

10 OPEN 1,8,2,“DENEME,S,R”
20 INPUT #1,A$
30 PRİNT A$
40 IF ST < > 64 THEN 20
50 CLOSE |
Görüldüğü gibi önce yazma mo-
dunda aynı dosyayı bir daha açıyor,
sonra da sonuna kadar okuyup satır
satır yazıyoruz. 40. satırda ST adlı
STATUS değişkenini kontrol edip
dosyanın bitip bitmediğini anlayabi-
liyoruz. En sonda da dosyayı kapa-

tıyoruz. Yukarıda verdiğimiz bazı değişiklikleri de yaparak çeşitli dosyalar yaratın ve onları bu programla okumaya çalışın. Ne zaman hata çıktığını, ne zaman beklediğinizden farklı sonuçlar oluştuğunu gözlemleyin. 10. satırda dosyayı açarken eğer o isimde bir SEQ dosyası yoksa, gene kırmızı ışık yanıp sönerek size haber verecektir. Bunu programımızın içine de koyabilirdik. Örneğin;

15 OPEN 2,8,15
16 INPUT # 2,A,A$,B,C
1? CLOSE 2
18 IF A < > 0 THEN
CLOSE 1:END

BU PROGRAM YANLIŞ! Halbuki ne kadar doğru duruyor, değil mi? 17. satıra kadar her şey iyi güzel... komut kanalını açıp gelen mesajı okuyoruz. Ama 17. satırda bu kanalı KAPATMAMAMIZ gerekiyordu. Başka dosyalar açıkken bu kanalı açmak onlara bir zarar vermez. Ancak açık olan komut kanalını kapatmanız, aynı zamanda o sırada açık duran diğer tüm dosyaların da kapanmasına yol açacaktır. Dolayısı ile 18. satırda her şey yolunda görünse ve program 20. satırdan devam etse bile, 1 numaralı kanal da 17. satırdaki komut kanalının kapanmasından etkilenerek kapanmış olacağından, INPUT # komutları işe yaramayacaktı. Kıssadan hisse, komut kanalı, eğer kullanılacaksa, programın EN BAŞINDA açılmalı ve EN SONUNDA kapanmalı, arada ellenmemelidir! Şimdi aşağıdaki programlardan biriyle dört satırlık bir sıralı dosya yarattığımızı düşünelim:

10 OPEN 1,8,2,“DEN,S,W”
20 PRİNT
30 PRİNT #1,“SATIR2”
40 PRİNT #1,“SATIR3”
50 PRİNT #1,“SATIR4”
60 CLOSE |

veya

10 OPEN 1,8,2,“DEN,S,W””
20 PRİNT #1,“SATIRI,SATIR2”
30 PRİNT # 1,“SATIR3,SATIR4”
40 CLOSE 1

Şimdi de bunu okuyacak çeşitli programlar görelim. Bunlar 1541 ile ilgili olmaktan çok, 64-1541 arasındaki bilgi alışverişini sağlayacak programlama tekniklerinin küçük bir gösterisi...

Disket sürücünüz en az bilgisayarınız kadar karmaşık ve mükemmel. O'nu iyi ve verimli kullanmak için çok şey öğrenmeniz gerekli. Ancak bundan sonra 1541'inizi tanıyabilirsiniz.

10 OPEN 1,8,2,'“DEN,S,R”
20
30 INPUT #1,B$
40 INPUT #1,C$
50 INPUT #1,D$
60 PRINT A$
70 PRİNT B$
80 PRINT C$
90 PRİNT D$
100 CLOSE |

veya

10 OPEN 1,8,2,“DEN,S,R”
20 INPUT # 1,A$,B$,C$,D$
30 PRİNT A$,B$,C$,D$
40 CLOSE i

(Bu programın kötülüğü, tek satırda yapılan INPUT #'un tüm değişkenlerinin toplam karakter sayısının 88'i geçmemesi gerektiği. Dolayısı ile, DS'in uzunluğu 88'den büyükse, başımız belada demektir.)

5 DIM A$(4)
10 OPEN 1,8,2,“DEN,S,R”
15 TO4
20 INPUT #1, AS(I)
30 NEXT 1
40 TO4
50 PRİNT
60 NEXT I
70 CLOSE |

veya

10 OPEN
20 INPUT #1,A$
30 PRINT A$
40 1F ST< > 64 THEN 20
1

Tüm bunlarda INPUT # kullandık ve bu komutun eksik yanlarını biliyoruz. Bunu düzeltmenin yolunun da GET #'den geçtiğini hatırlıyor olmalısınız. GET # ile kayıtları okurken kayıtlar arasındaki ayırımı biz yapacağımız için hangi tahta perde rolünü oynayacağına karar vermek bizim işimiz. Eğer sadece $0D byte'ını ayırıcı olarak kabul edersek, yukarıda verdiğimiz dört satırlık dosya yaratan iki programın sonuçları farklı olacak demektir. INPUT # ile her ikisinden de dört kayıt okuduğumuz halde, GET # ile birincisi dört, ikincisi ise iki kayıt halinde görünecektir. Şimdi böyle bir okumayı yapan programı görelim:

10 OPEN 1,8,2,“DEN,S,R”
IŞ
20 GET #1,N$
25 IF X$-CHRS(13)
THEN 60
30 XS
401FST < > 64 THEN 20
45 PRINT A$
50 CLOSE 1
55 END
60 PRINT A$
70 IF ST < > 64 THEN 15
80 CLOSE 1

Görüldüğü gibi dosyayı karakter karakter okuyup kayıtları oluşturuyoruz. Bu arada devamlı ayırıcı byte'ın ve dosya sonunun gelip gelmediğinin de kontrolünü eksik etmiyoruz. Böylece INPUT # için 88 olan karakter sayısı sınırını 255'e çıkarmış oluyoruz. 255'in nedeni, BASIC'te bir değişkenin en fazla 255 karakter alabilmesi. Bunun için elimizden bir şey gelmez. Disketin üzerinde daha önceden yaratılmış bir sıralı dosyanın arkasına yeni kayıtlar eklemek istediğimizde ise A modunu kullanacağımızı söylemiştik. Şimdi DENEME dosyamıza dört satır daha ekleyelim:

10 OPEN 1,8,2,“DENEME,S,A”
20 PRİNT #1,“DONALD”
30 PRİNT & 1, “DUCK”
40 PRİNT
S0 PRİNT
60 CLOSE |

10. satırın sonundaki A parametresine dikkat!

Şimdi de bu dosyayı en son verdiğimiz GET # metodu ile okuyun. Tabii dosya adı olarak DEN yerine DENEME kullanılacak. Yeni satırların dosyanın arkasına eklendiğini göreceksiniz. Ama diyelim ki dosyanın ortasına bir kayıt eklemek istediniz. Bunu, ya dosyanın tamamını bilgisayarın hafızasına okuyup istediğiniz sırada geri diskete yazarak (tabii ki, eski dosyayı sildikten sonra!) ya da şimdi vereceğiniz yöntem ile direkt disketin üzerinde halledebilirsiniz. Yöntem, dosyanın kayıt kayıt bir kopyasını çıkarmaya, bu arada da istenen yere önceden hazırlanmış yeni kaydı yerleştirmeye yarıyor. Ancak uzun dosyalarda bu iş de uzun zaman alacaktır. Ayrıca disketin üzerinde, dosyanın eski uzunluğundan yeni kaydedilecek bilginin uzunluğu kadar fazla boş yer olması gerekiyor. Yani disketin yarısını kaplayan bir dosyanız varsa bu işlemi uygulayamazsınız. Gelelim programa...

5 KX-10
6 K$- “YENİ KAYIT”
10 OPEN 1,8,2,“DEN,S,R”
11 OPEN 2,8,3,“DENX,S,W”
12 K-0
16
20
25 IF X$- CHRS(13)
THEN 56
30
401FST< > 64 THEN 20
411FK < > KX THEN 45
42 PRİNT 2,K$
45 PRINT 2,A$
50 GOTO 80
56 IF K> KX THEN 60
57 PRİNT #2,K$
60 2,A$
70 1F ST <> 64 THEN 15
80 CLOSE |
90 1FK > KX THEN 98
95 PRİNT #2,K$
98 CLOSE 2
99 OPEN 1,8,15,“S:DEN”
100 PRİNT #1,“R:DEN—- DENX”
110 CLOSE |

Program bir dosyadan diğerine kayıt kopyalarken devamlı olarak kaçıncı kaydı kopyaladığının çetelesini tutuyor. Eğer o sırada kopyalayacağı kayıt, ortaya girmesi gereken kayıtla aynı numarada ise önce yeni kayıt yazılıyor, sonra eski kayıt kopyalanıyor. Eğer eski dosyadaki kayıtlar bittiği halde yeni kayda sıra gelmemişse (Örneğin DEN'den sadece 3 kayıt varsa) yeni kayıt dosyanın sonuna ekleniyor. En sonda da, eski dosya silinip yeni dosyanın adı eski dosyanın adına çeviriliyor.

Artık işin sonuna yaklaştık. Bir de

M modu olduğunu bahsedip n'aptığından kısaca söz etmiştik. Şimdi onun da ayrıntısına girelim. Diskete dosyayı yazarken 1541'in içinde buffer kullanıldığını biliyorsunuz. Siz CLOSE ile dosyayı kapattığınızda bu buffer'daki en son bilgi kırıntıları da dosyaya eklenir ve directory'de dosyanın sağlam kapandığı işaretlenir. Eğer CLOSE yapmadan disketi çıkarırsanız, dosyanın sonu eksik kalacaktır ve directory'de de kapanmamış görünecektir. Bunu da, directory dökümünde, program türünün yanında çıkacak yıldız karakterinden anlayabilirsiniz. Böyle bir dosyayı okumaya kalkıştığınızda kırmızı ışık acı acı yanıp sönmeye başlayacak ve WRITE FILE OPEN hatası gelecektir. Peki bu dosyaları okumanın hiç mi yolu yok? Bilgiler disketin üzerinde olduğu halde kaybolmuş mu sayacağız? Tahmin ettiğiniz gibi hayır. Bu gibi dosyaları M modu ile açıp, kayıtlarını bir başka dosyaya göndermemiz, bu yeni dosyayı doğru dürüst kapatmamız ve eski dosyayı da silmemiz yeterli olacaktır. Tabii, disketinizde yeni dosyayı alacak yer varsa. Eğer yoksa, önce kapanmamış dosyanın ilk birkaç kaydını hafızaya okuyup sonra başka bir diskette yaratacağınız yeni bir dosyaya yazmanız gerekir. Bu yeni dosyayı güzelce kapattıktan sonra eski dosyanın kopyaladığınız ilk kayıtlarını atlayarak, sonra gelen kayıtlarından olduğu kadarını gene hafızaya okumak (M modu ile, tabii ki) ve öbür disketteki dosyayı bu kez 8 modunda açıp hafızadaki kayıtları ona ekleyip yeniden kapatmak ve bu işlemi ilk dosya bitinceye kadar devam ettirmek gerekecektir. Zahmetli bir iş, ama hiç yoktan iyidir. M modunu kullanarak küçük bir örnek verelim ve hatalı DOSYAZ2'ye kopyalayalım:

10 OPEN 1,8,2,“DOSYAL1,S,M”
20 OPEN 2,8,3, “DOSYA2Z,S,W”
30 INPUT #1,AS$
40 PRİNT #2,A$
> 64 THEN 30
60 CLOSE 2
70 CLOSE 1
80 OPEN 1,8,15
90 PRİNT
95 CLOSE
İşte bu kadar... Artık bu bilgilerin
aşığı altında kendi sıralı dosyalama
sisteminizi geliştirebilmeniz lazım...
Relatif dosyalarda buluşmak üzere...