home *** CD-ROM | disk | FTP | other *** search
/ 8bitfiles.net/archives / archives.tar / archives / genie-commodore-file-library / Information / CONFUSION-IS-RELATIVE < prev    next >
Encoding:
Text File  |  2019-04-13  |  21.0 KB  |  446 lines

  1.  
  2.              Confusion is Relative
  3.               by deb! Christensen
  4.  
  5.               (C)opyright 1986 all rights reserved
  6.  
  7.      The Eighth Wonder of the World should be Commodore Relative
  8. files.  The wonder is that anyone can make sense from the
  9. documentation which CBM supplies for using these files in 2.0 BASIC!
  10.   A highly powerful random access file type, Relative files are
  11. worth every ounce of perspiration you put into them.  Allowing the
  12. programmer to define fields within each record and retrieve
  13. information from any given record number this file type is easily
  14. accessible from BASIC and can substantially speed up editing tasks
  15. to disk records.  If you'll follow closely here, I'll try to remove
  16. the guesswork as well as the mystery from Commodore Relative
  17. Records.
  18.      A warning first:  Do not try to work with a Relative file until
  19. you are thoroughly familiar with SEQuential files, BASIC disk
  20. programming and using the drive command channel!  Relative files
  21. depend heavily upon programming and planning.  All good Data Base
  22. programs use this file type because any piece of information can be
  23. easily accessed in the file without having to read all the
  24. information which precedes it.  That information can also  also be
  25. changed and written back into the file without even touching another
  26. file entry!  Anyone who has ever had to sift through a very long
  27. SEQuential file to find one piece of information, update the data
  28. and wait for the file to write back to the disk should very quickly
  29. see the advantages that this kind of random access will give you.
  30.      There is a catch to this, though.  The DOS must know where to
  31. go to find the information you want to retrieve.  With careful
  32. planning and programming, your software can keep track of this for
  33. you.  Very literally, every position within the file is available
  34. for instant access.  Poor planning will result in a tangled web of
  35. confusion and possibly a whole stack of disk errors!  To avoid
  36. chaos, be sure to define the task on paper before even touching your
  37. computer.  I know this probably sounds like I'm about to dish out a
  38. Flowcharting 101 course, but there is no substitute for crystalizing
  39. a program idea in an outline before undertaking the actual BASIC
  40. coding needed.
  41.      First, define the purpose of the program and any special
  42. conditions which need to be incorporated.  My example here is going
  43. to be a file which holds questions and the correct answers.  The
  44. program will need to be able to read the question from the file,
  45. print it to the screen, ask the user for the correct answer and then
  46. compare it to the correct answer stored in the file.  The greatest
  47. advantage with a Relative file is that the access time for the first
  48. piece of information should be about the same as the last entry in
  49. the file!  This is very important when the free memory of your
  50. computer is nearly full and a large amount of information must be on
  51. hand for easy access.
  52.      There are several steps involved in using a Relative file.  The
  53. file must be created first.  That sounds very obvious, but because
  54. of the unique way a relative file is used, you can OPEN an existing
  55. file on the disk just once, and either Read from it or Write to it!
  56. Consequently, there is a specific way to create that Relative file
  57. on the disk for the first time.  After the initial creation of the
  58. file, anytime you OPEN a relative file it is available for Reading
  59. or Writing when the correct commands have been issued.  You can
  60. easily replace just one piece of information in the file without
  61. disturbing or having to re-write the rest of the file through
  62. careful positioning of the read-write head.  Handy sounding, isn't
  63. it?
  64.      Every Relative file is divided into what are known as Records.
  65. To understand what a Record is, imagine a file box full of 3 x 5
  66. index cards.  This is your address file, and each card contains only
  67. one name and address.  The entire box is referred to as the File and
  68. each individual card is one Record within the file.  Each card, or
  69. Record is the same size, 3" x 5", or it wouldn't fit in the file,
  70. would it?  Written on each Record, or card, is a name on the top
  71. line, followed by the address, city, etc.  These separate lines are
  72. called Fields and are the individual entries you make in each
  73. Record.  So, each individual Record can contain several Fields.  A
  74. typical address Record looks like this:
  75.  
  76.           John Jones
  77.           123 Main St.
  78.           Anywhere, CA 90000
  79.           (209) 555-1234
  80.  
  81.  
  82.      The four Fields from the Record above would be:
  83.           Name
  84.           Address
  85.           City, State, ZIP
  86.           Phone
  87.      When a Relative file is created, the size of each record is
  88. defined and cannot be changed.  The size of the record is called the
  89. record length and is the combined total of maximum number of
  90. characters from each field for that record entry.  This is a
  91. critical part of planning.  If a record is not large enough, part of
  92. the data being written will be dropped, and if there is too much
  93. room, you will just be wasting precious disk storage space.  In the
  94. example for the question and answer file, I am going to allow 89
  95. characters for the question and 24 characters for the answer.
  96.      Each record within a Relative file can contain up to 254
  97. characters.  There will only be the two fields in each record of
  98. this file, so just add up the maximum characters from each
  99. anticipated field to find the total length for each record.  That
  100. gives us a record length of 113 characters, well under the 254
  101. maximum.  It is a very good idea to allow an extra character in each
  102. field to separate the information.  I use carriage returns to mark
  103. the end of each field, which store as a 13 or CHR$(13) in the file.
  104. So, add two more characters to the record length, and that is all
  105. the information needed to create the file.
  106.      The file can be created in the direct mode or it can be created
  107. with a program.  I'm going to use program lines here.  You'll find a
  108. small program in the appendix which can be used to create any
  109. Relative file.  When the DOS is asked to create a new Relative file
  110. a Side Sector is created for that new file.  In the Side Sector the
  111. DOS stores all the pointers to the physical location of each record
  112. number.  You'll probably never even know where that Side Sector is,
  113. but it will be working hard to make sure that each of the designated
  114. records are available to the program by merely calling the record
  115. number.  The Side Sector is an operation of the DOS.  Neither the
  116. program or the programmer has to keep track of it!
  117.      Now, lets name the file and put it on the disk.  The number of
  118. characters per record will follow the file name as a CHR$ value.
  119. You cannot create a relative file without it!  This file will be
  120. named "TEST".
  121.  
  122.           10 REM CREATE RELATIVE FILE
  123.           20 OPEN3,8,3,"TEST,L,"+CHR$(115)
  124.      Make sure that you type it in exactly as specified above.  The
  125. most common errors include leaving out the comma right after the
  126. secondary address and leaving out that second comma within the
  127. quotes, following the "L".  And yes, the plus sign is part of the
  128. syntax also.  Here is the breakdown of the OPEN statement:
  129.  
  130.          OPEN file#,device#,channel#,"name,L,"+CHR$(length of
  131. record)
  132.  
  133.      The file should be CLOSEd next.
  134.  
  135.           30 CLOSE3
  136.  
  137.      RUN the small program and then take a look at the directory.
  138. (You may want to SAVE the program to a disk first, though.)  You can
  139. see the REL for the file type on the directory entry for TEST.  It
  140. is done, and the Relative file named TEST now resides on the disk.
  141.      I am sure it will not surprise you, but Relative files do have
  142. some of their own rules.  The SAVE with Replace option does not work
  143. with a Relative file.  If you need to get rid of a Relative file,
  144. you can use the SCRATCH command, and start all over again with a new
  145. file, or you could erase the whole disk with a NEW command.  Some
  146. backup programs will not copy a Relative file.  Don't panic, I know
  147. that "1541 Copy" will do it for sure.  This is a public domain
  148. program and is available from most user groups.  Remember those Side
  149. Sectors? The DOS uses them to keep track of the file.  These Side
  150. Sectors are automatically updated by the DOS and you do not see
  151. them.  Although they are allocated in the BAM the Side Sector does
  152. not even have a separate entry in the Directory.  It is considered
  153. part of the overhead and housekeeping space taken up by the Relative
  154. file itself.  Many copy and backup programs do not look for them,
  155. and that is why Relative files may not copy.  Because of these Side
  156. Sectors, the total storage on the diskette is not quite as large
  157. when a Relative file format is being used.
  158.     The relative file you just created is now ready for either
  159. Reading or Writing anytime is is OPEN.  Storing and retrieving from
  160. this file will require several pieces of information.  When you
  161. created the Relative file you told the DOS how many characters would
  162. be in each record.  That relative file will now be sectioned off
  163. into 115 character records.  Each record will be exactly the same
  164. size as every other record in the file, just like you had used the
  165. same cookie cutter on a large piece of dough!  Once you tell the DOS
  166. what size of "cookie cutter" to use, each record which is added to
  167. this file will always be 115 characters long and will be ready to
  168. accept the data which you need stored in it.  The DOS and the Side
  169. Sectors will keep track of the physiscal location of each record. To
  170. access the information in any record, only the record number is
  171. needed.
  172.      A relative file has no pre-determined size and will expand
  173. dynamically as you write to the new record numbers.  This will take
  174. a bit of time if the DOS must find space on the diskette, allocate
  175. the sector in the BAM and update the Side Sector, as well as write
  176. to the file itself.  This whole process can be speeded up
  177. considerably if the maximum number of records can be anticipated.
  178. When the last record number is known, the Relative file can be
  179. forced to write to that last record, thereby also writing all the
  180. records from the beginning of the file to that last record number
  181. and allocating all that space on the disk.  Although this will take
  182. a little time at the beginning, it is a good habit.
  183.      When you need to write to any record on a relative file,
  184. whether it is a new record or an old one, you need to send a
  185. position command to the drive.  This will give the DOS the neccesary
  186. information to compute the exact position for the read/write head
  187. and allow you to store the information where you can easily retrieve
  188. it later with the same positioning command.  To send this
  189. positioning command to the drive you will need to know the record
  190. number. So, pulling a number out of the hat, the maximum record
  191. number in this file will be 335.  By positioning the drive to record
  192. number 335, the file can be forced to write that last record.  All
  193. positioning commands must be sent to the drive in the form of a
  194. CHR$.  The maximum allowable number which will fit into a CHR$ is
  195. 255.  This represents the 8-bit limit of one byte, with all bits on
  196. (on means each bit is set to 1, totalling 255 in decimal).  It is
  197. very common to need more than just 255 records for one file, so the
  198. record number is sent to the drive in the standard low byte-high
  199. byte format of 6502 machine code.
  200.      This sounds overwhelming at first, but is really quite simple
  201. to calculate.  The high byte is calculated first by dividing the
  202. record number by 256.  The low byte is then derived from the
  203. remainder.  The low byte for 335 is 79 and the high byte is 1.  The
  204. BASIC syntax for this formula looks like this:
  205.  
  206.           N=335:HI=INT(N/256):LO=N-(HI*256)
  207.  
  208. You can double check the formula results by multiplying the high
  209. byte times 256 and adding the low byte.  Here are some more examples
  210. for you.  Please notice that the low byte will always preceed the
  211. high byte.
  212.  
  213.           low byte       high byte       decimal number
  214.              0               1             =  256
  215.              1               2             =  513
  216.             36               0             =   36
  217.            232               4             = 1000
  218.  
  219.      Here is what the syntax looks like for a position command:
  220.  
  221.           PRINT#15,"P"CHR$(CHANNEL#)CHR$(LO)CHR$(HI)
  222.  
  223.      Obviously the command channel must be open as well as the
  224. relative file.  To accomplish this use the following line of BASIC:
  225.  
  226.           40 OPEN15,8,15:OPEN3,8,3,"TEST"
  227. When accessing a relative file it is always a good idea to check the
  228. error status!  Use a subroutine to do this.
  229.           42 GOSUB500
  230.          500 INPUT#15,E,ER$,T,S:IFE<>0THEN?E;ER$;T;S:STOP
  231.          510 RETURN
  232. Before accessing the file itself, the position command must be
  233. issued first.  This command will always be sent to the command
  234. channel, #15.
  235.           50 PRINT#15,"P"CHR$(3)CHR$(79)CHR$(1)
  236.      The first CHR$ value is the channel number of the Relative
  237. file, which was specified as the secondary address in the OPEN
  238. command.  The next value is the low byte of the record number,
  239. followed by the high byte of the record number.  Again, check the
  240. disk status after using this command.
  241.           55 GOSUB500
  242.      A word of caution!  The record number you are writing does not
  243. exist yet, and it will return error number 50, indicating that the
  244. record does not exist.  Of course this is no surprise, is it?  That
  245. is the whole purpose of doing this, to create the record.  When the
  246. program stops after this error message, just type in :
  247.           CONT
  248. The program will continue to execute from the place it was STOPped
  249. after this command.  This number 50 error message does not matter
  250. under these circumstances, but it must be read and cleared from the
  251. disk status.  At the end of this chapter is a LISTing of the final
  252. version of this program which includes one technique for handling a
  253. RECORD NOT PRESENT error without STOPping the program.  The disk
  254. drive is now in position for you to write to the new record number
  255. 335 in your relative file!  Accomplish this with the following line
  256. of programming:
  257.             60 PRINT#3,"This is the Last Record!"
  258.             65 GOSUB500
  259.      The read/write head was already positioned through the command
  260. channel in line 50, and the actual information being written into
  261. the file is written to the File Number of the Relative file, just
  262. like you would send it to a SEQuential file!
  263.      CLOSE the files and make everything nice and tidy.  Many times
  264. the DOS buffers still hold some of the information which you sent to
  265. the file.  If the file is not CLOSED you will loose important DATA
  266. and pointers.  The warning to always CLOSE a file still applies to a
  267. Relative file.
  268.             70 CLOSE3:CLOSE15
  269.      Just as in other file operations, the command channel must be
  270. the first one OPENed and the last one CLOSEd.  Closing the command
  271. channel will automatically close all other files.  Be very careful!
  272.      Although you can have as many Relative files on one disk as
  273. will fit, only one Relative file can be OPENed at one time.  A
  274. Relative file takes 2 of the DOS RAM buffers, one for the file and
  275. the extra one for the Side Sectors.  Trying to OPEN a second
  276. Relative file will return a NO CHANNEL error message from the drive.
  277. I know you have read that 2 Relative files can be OPEN
  278. simultaneously, but don't believe it!  Commodore forgot to update
  279. the manuals and although prior IEEE drives have more channels to
  280. work with, a 1541 has a total of only 3 channels you can access with
  281. SEQuential or Relative files.  Since the Relative file uses 2 of
  282. these channels, there is still one channel free, and a SEQuential
  283. file can be OPENed along with the Relative one.
  284.      Be sure to SAVE this program.  After doing that, look at the
  285. directory on your disk.  You should see a remarkable difference in
  286. the number of blocks which the Relative file called TEST uses!  By
  287. writing to that last record, you not only created all the
  288. intermediate records, but you also forced the DOS to allocate the
  289. sectors on the disk, saving the space from being used for something
  290. else.  This is really the best technique to use.  Can you imagine
  291. being in the middle of a program and finding out that there is no
  292. more room on the disk to finish writing your data?  That is a
  293. situation to be avoided at all costs!
  294.      Even though the only record which contains any information is
  295. number 335, record numbers 1 through 334 exist on your disk.  The
  296. first data byte in each empty record will contain a chr$(255) to
  297. indicate it is empty, and the rest of the 115 bytes in the record
  298. contain nulls, or binary zeros.  When you partially fill a record,
  299. the unused bytes in the record will remain nulls.  It is important
  300. to realize that any subsequent entries to that same record which are
  301. shorter than the first entry will not result in the rest of the
  302. record being filled with nulls again.  All bytes after the new data
  303. is written will remain untouched.  This is why it is so very
  304. important to use a field separator in a relative file.  Each record
  305. can have extra space in it, which may be filled with either nulls or
  306. old data.  As long as the program knows what the field separator is,
  307. this old data will can be ignored.
  308.      This is what the Relative file looks like now:
  309.  
  310.                Records 1 to 334:
  311.           Byte 1        Bytes 2-115
  312.           ASCII 255       nulls-CHR$(0)
  313.  
  314.                Record # 335:
  315.           Bytes 1-24 contain the ASCII for these characters:
  316.  
  317.            -----------------------------------------------
  318.            T h i s   i s   t h e   L a s t   R e c o r d !
  319.            -----------------------------------------------
  320.  
  321.           Byte 25       Bytes 26-115
  322.           CHR$(13)        nulls-
  323.           <RETURN>        CHR$(0)
  324.  
  325.            Program Listings
  326.  
  327.            CREATE THE FILE! 
  328.  
  329.  
  330.  
  331. 10 rem create relative file chapter 10 
  332. 20 open3,8,3,"test,l,"+chr$(115) 
  333. 30 close3 
  334. 40 open15,8,15:open3,8,3,"test" 
  335. 45 input"highest record number";n 
  336. 46 hi=int(n/256):lo=n-(hi*256) 
  337. 50 print#15,"p"chr$(3)chr$(lo)chr$(hi)chr$(1) 
  338. 55 gosub500:ife<>0thenprinte;er$:ife<>50thengosub510 
  339. 60 print#3,"The last record is number";n 
  340. 65 gosub500:ife<>0thenprinte;er$:ife<>50thengosub510 
  341. 70 print"a successful file write!":close3:close15 
  342. 100 print" Now, lets see if it is where it is      *supposed* to be!"
  343. 110 open15,8,15:open2,8,2,"test" 
  344. 115 gosub500:ife<>0thengosub510 
  345. 120 print#15,"p"chr$(2)chr$(lo)chr$(hi)chr$(1):gosub500:ife<>0thengosub510
  346. 125 input#2,a$:printa$:gosub500:ife<>0thengosub510 
  347. 130 close2:close15:end
  348. 499 end
  349. 500 input#15,e,er$,t,s:return 
  350. 510 printe,er$,t,s:stop 
  351. 515 return 
  352. ready. 
  353.  
  354.  
  355.           WRITE THE RECORD 
  356.  
  357.  
  358.  
  359. 10 rem test file 115 characters 
  360. 20 rem      per record 
  361. 30 : 
  362. 39 rem   ***  open files  *** 
  363. 40 open15,8,15:open3,8,3,"test":gosub500:ife<>0thengosub510 
  364. 50 rem position 1 has question (field 1) 
  365. 60 rem position 90 has answer  (field 2) 
  366. 90 rem   ***  write file  *** 
  367. 100 fori=1to11:rem i=record number  
  368. 102 :  
  369. 105 rem channel 3, recordi, position 1  
  370. 110 print#15,"p"chr$(3)chr$(i)chr$(0)chr$(1):gosub500:ife<>0thengosub510  
  371. 112 :  
  372. 115 rem put question in file 3 first position 
  373. 120 reada$:print#3,a$:gosub500:ife<>0thengosub510 
  374. 122 : 
  375. 125 rem position 90 in record i 
  376. 130 print#15,"p"chr$(3)chr$(i)chr$(0)chr$(90):gosub500:ife<>0thengosub510
  377. 132 : 
  378. 135 rem store answer at position 90 
  379. 140 reada$:print#3,a$:gosub500:ife<>0thengosub510 
  380. 150 nexti 
  381. 160 close3:close15:end 
  382. 290 end 
  383. 299 rem  ***  contents for file  *** 
  384. 300 data "How many tracks on a 1541 formatted     diskette?","35" 
  385. 310 data "On which track does the Directory sit?","18" 
  386. 320 data "What is the maximum number of SEQuential Files OPEN at the same time?"
  387. 325 data "3"
  388. 330 data "What is the maximum number of Relative  files OPEN at once?","1"
  389. 340 data "Can 1 Relative file and 1 SEQuential    file be used simultaneously?"
  390. 345 data "yes" 
  391. 350 data "How do you get rid of a file marked with an asterisk?","validate"
  392. 360 data "What is the channel number for the      command channel?","15"
  393. 370 data "Can channel 1 or 0 be used for secondary address in OPEN statement?"
  394. 375 data "no" 
  395. 380 data "What is the correct abbreviation for the BASIC command,PRINT#?"
  396. 385 data "pR" 
  397. 390 data "Can you read or write to the same OPEN  Relative file?","yes"
  398. 395 data "Can an existing Relative file get larger without making a new one?"
  399. 396 data "yes" 
  400. 499 rem  ***  read error  *** 
  401. 500 input#15,e,er$,t,s:return 
  402. 510 printe,er$,t,s:stop 
  403. 515 return 
  404.  
  405.  
  406.  
  407.         RANDOMLY READ FILE
  408.  
  409.  
  410. 6 open15,8,15:open3,8,3,"test":gosub500:ife<>0thengosub510
  411. 10 goto100:rem skip subs
  412. 20 x$="":a$=""
  413. 21 get#3,x$:ifx$=chr$(13)thenreturn
  414. 22 printx$;:a$=a$+x$:goto21
  415. 30 x$="":a$=""
  416. 31 get#3,x$:ifx$=chr$(13)thenreturn
  417. 32 a$=a$+x$:goto31
  418. 40 x$="":g$=""
  419. 41 getx$:ifx$=""then41
  420. 42 ifx$=chr$(13)thenprint:goto50
  421. 44 ifx$=chr$(20)thenprint" ";:g$=left$(g$,len(g$)-1):goto41
  422. 45 printx$;:g$=g$+x$:goto41
  423. 50 ifg$=a$thenprint"correct answer!":return
  424. 55 print"correct answer is ";a$:return
  425. 100 dimfl(11):forx=1to11:rem i=record number
  426. 105 i=int(rnd(1)*11)+1
  427. 106 iffl(i)then105
  428. 107 fl(i)=1
  429. 108 print"Question number";i
  430. 110 print#15,"p"chr$(3)chr$(i)chr$(0)chr$(1)
  431. 120 gosub20:print
  432. 130 print#15,"p"chr$(3)chr$(i)chr$(0)chr$(90)
  433. 140 gosub30
  434. 145 print:print"q    Your answer? ";:gosub40
  435. 150 print:nextx
  436. 160 close3:close15:end
  437. 290 end
  438. 500 input#15,e,er$,t,s:return
  439. 510 printe,er$,t,s:stop
  440. 515 return
  441. ready.
  442.  
  443.  
  444. As You can see, it is only half done!
  445. Use what you've learned to improve and continue from here!
  446.