Liberty Basic is develeopped by Carl Gundel Original Newsletter compiled by Alyce Watson and Brosco Translation to HTML: Raymond Roumeas
In this issue:
- Using Random files - Part 1
Ok - lets first understand what a RANDOM file is.
Basically all files (including text files) are RANDOM files! Its just a stream of data that you can start reading anywhere - rather than at the first position - and you retrieve records of data rather than text strings.
Within LB, life has been simplified for us. We can tell LB that we have a record or structure for the data, and it gets it for us. If you were accessing a file as random in some other Windows programming languages you would need to keep track of the record length and request a specific number of bytes and the byte starting position within the file - with LB we simply tell it the record number that we want to read or write.
Here's a very simple example of using a Random file in LB. Suppose that we wanted to create a catalogue of our collection of Video Cassettes. Each cassette has a number on its label, starting with 0001 and incrementing as we add to our collection - it will be OK if some numbers are missing. We will keep track of the Movie name and the main star in the movie. The first program will record a couple of cassettes that are already in our collection.
nomainwin open "video.txt" for random as #f len=52 '*** note 1 field #f, _ 4 as cNum, _ 24 as name$, _ 24 as mainActor$ cNum = 1 name$="Golden Eye" mainActor$ = "Pierce Brosnan" put #f, 1 cNum = 3 name$ = "Ransom" mainActor$ = "Mel Gibson" put #f, 3 close #f notice "Initial database has been created" end ***** Note 1
First of all - read the second statement of the program very carefully! On the end of the OPEN statement there is "len=49". This is the length of the record. This must EXACTLY match the total length of all FIELDs specified in the next statement.
The file has been given a name of "video.txt" - you could choose any name you liked - plus the extension could be any name you wanted. I used the extension of .TXT so that you could run the program and then, using Windows Explorer - simply double click on the file and Notepad would display the contents of our database. Please do this now - 'cut' the program above - 'paste' it into LB and then run it.
Then use Notepad to examine the contents of "video.txt".
When you view the file, click on EDIT and then WORDWRAP so that you can see all the data. Notice that we added record #1 and then record #3. LB inserted a blank record #2 for us.
Also note that the cassette number (cNum) is displayed as text, even though its a number within our program - LB does that for us. All data in our database is stored as text - and converted to the correct format for use in the program.
Next, we will have a very simple program to list the contents of our database:
open "video.txt" for random as #f len=52 field #f, _4 as cNum, _ 24 as name$, _ 24 as mainActor$for i = 1 to 3get #f,i print cNum;" ";name$;mainActor$ next inotice "Initial database has been displayed" close #f end
Cut and Paste this program to LB and run it. You will see the contents listed.
Now that we have seen how easy it is to read and write to random files - lets build a slightly more realistic program to add, update, delete and browse our database.
' Sample program to update a database ' Brosco - June 98 (Newsletter #9) ' open "video2.txt" for random as #f len=49 field #f, _ 1 as active$, _ 24 as name$, _ 24 as mainActor$ nomainwin WindowWidth = 320 WindowHeight = 230 statictext #w.1, "Cassette Number:", 10, 40, 130, 20 statictext #w.2, "Movie Name:", 10, 70, 130, 20 statictext #w.3, "Main Star:", 10, 100, 130, 20 statictext #w.4, "Status:", 10, 175, 65, 20 statictext #w.status, "", 80, 175, 240, 20 textbox #w.cn, 150, 40, 30, 25 textbox #w.movie, 150, 70, 150, 25 textbox #w.star, 150, 100, 150, 25 button #w.add, "Add", [add.movie], UL, 70, 140, 50, 25 button #w.upd, "Update", [update.movie], UL, 130, 140, 50, 25 button #w.del, "Delete", [delete.movie], UL, 190, 140, 50, 25 button #w.exit, "Quit", [close.w], UL, 250, 140, 50, 25 button #w.prev, "<--Prev", [previous], UL, 70, 5, 60, 25 button #w.next, "Next -->", [next], UL, 160, 5, 60, 25 button #w.default, "Get", [get.movie], UL, 10, 140, 50, 25 open "Movie Database" for dialog as #w print #w, "trapclose [close.w]" print #w.cn, "!setfocus" [loop] input var$ goto [loop] [previous] cNum = cNum - 1 if cNum < 1 then cNum = 1 print #w.status, "You are at the start of the database" goto [loop] end if get #f, cNum if active$ <> "1" then [previous] gosub [display.movie] goto [loop] [next] cNum = cNum + 1 if cNum > lof(#f) / 49 then cNum = lof(#f) / 49 print #w.status, "You are at the end of the database" goto [loop] end if get #f, cNum if active$ <> "1" then [next] gosub [display.movie] goto [loop] [display.movie] print #w.cn, cNum print #w.movie, name$ print #w.star, mainActor$ print #w.status, "" print #w.cn, "!setfocus" return [get.movie] print #w.cn, "!contents?" input #w.cn, cNum if cNum < 1 then notice "Get error!" + chr$(13) + _ "Cassette number must be greater than 0" goto [loop] end if if cNum > lof(#f) / 49 then 'check if the record exists [get.error] notice "Get Error!" + chr$(13) + _ "This record doesnt exist" goto [loop] end if get #f, cNum if active$ <> "1" then [get.error] gosub [display.movie] goto [loop] [add.movie] print #w.cn, "!contents?" input #w.cn, cNum if cNum < 1 then notice "Add error!" + chr$(13) + _ "Cassette number must be greater than 0" goto [loop] end if if cNum <= lof(#f) / 49 then 'check if the record exists get #f, cNum 'check if the record is active if active$ = "1" then notice "Add error!" + chr$(13) + _ "This Cassette exists in the database." + chr$(13) + _ "Select GET - then Update" goto [loop] end if end if gosub [write.record] print #w.status, "Movie has been added." goto [loop] [update.movie] print #w.cn, "!contents?" input #w.cn, cNum if (cNum < 1) or (cNum > lof(#f)/49) then [update.error] notice "Add error!" + chr$(13) + _ "Cannot update non-existant record." goto [loop] end if get #f, cNum if active$ <> "1" then [update.error] gosub [write.record] print #w.status, "Movie has been updated." goto [loop] [delete.movie] print #w.cn, "!contents?" input #w.cn, cNum if (cNum < 1) or (cNum > lof(#f)/49) then [delete.error] notice "Delete error!" + chr$(13) + _ "Cannot delete non-existant record" goto [loop] end if get #f, cNum if active$ <> "1" then [delete.error] active$ = "" name$ = "" mainActor$ = "" put #f, cNum gosub [display.movie] print #w.status, "Movie has been deleted." goto [loop] [write.record] print #w.movie, "!contents?" input #w.movie, name$ print #w.star, "!contents?" input #w.star, mainActor$ active$ = "1" ' show the entry is valid put #f, cNum return [close.w] close #w close #f end
Cut and Paste the above program to the LB editor and then run the program.
A very good way to see how a program works is to use LB's Debug mode and Step through the program.
Instead of storing the CassetteNumber in the database, we used that as the physical record number in that database. That is, if you add Cassette 0010, we will write the record in position 10 of the database.
if cNum > lof(#f) / 49 then
lof(#f) returns us the length of the file (in bytes). By dividing by 49 - the length of the FIELD structure, we know how many records exist on the database. We need to know this so that we dont try to GET non-existant records - that would cause an error and crash the program.
***********
OK - so what's wrong with this program?
1) First the KEY to the database must be a number, and unless we want to create a very large file, the keys should start at 1 and have very few 'gaps'.
2) To re-use deleted space - we must know the available record numbers.
3) If we wanted to find all the movies that starred our favourite actor, we would have to scan the entire database.
Next issue I will address these issues and, hopefully I will also have the problems in my DBDLL sorted out so that we can add a very fast indexing access method.
If you would like to discuss any of the code or techniques used here, please use my message board at:
and ideally, include "NL0009" is the Subject of the posting.
Also see - Using Random files - Part 2
Also see - Using Random files - Part 3
Newsletter written by: Brosco. Comments, requests or corrections to: brosco@orac.net.au Translated from Australian to English by an American: Alyce Watson. Thanks Alyce.