12-15-2022, 11:51 AM
QB64 added OPEN FOR BINARY to sequential files. Using it speeds up the process of LINE INPUT. So instead of...
OPEN "MYFILE.DAT" FOR INPUT AS #1
DO
LINE INPUT #1, a$
LOOP UNTIL EOF(1)
CLOSE #1
we do...
OPEN "MYFILE.DAT" FOR BINARY AS #1
DO
LINE INPUT #1, a$
LOOP UNTIL EOF(1)
CLOSE #1
Now a couple of things to note here:
1) ...FOR INPUT won't create a non-existing file, but FOR BINARY will.
2) An empty ...FOR INPUT file will just exit the loop. An empty ...FOR BINARY will error out.
So here is how to bullet proof the ...FOR BINARY method:
I've made use of sequential files that can overwrite data so I'm just as happy using them as random access, and I don't have to be concerned about record numbers or the length of the records. Overwriting is a bit more involved in sequential files, as it requires writing to a temp file. Basically write all data up to the block you are hanging to the temp file then write the changed data then write the remaining data. Now just kill the original database file and name the temp file as the database file.
I've worked with sequential files using an "EOR" as my made up End of record marker. The structure is pretty much what Steve described. Nice in that I could put whatever I wanted into each labeled record. In other words, no pattern required, very flexible so I don't need a structure. All I did to find what I wanted out of file was add an identifier to the line of data then parse it out while line inputting it...
[name] Clippy
[date] 01-01-2000
[assignment] Math 101
[grade] F
[comments] Clippy is an idiot.
[EOR]
Now it doesn't even matter if I do the next record in this order, I can search what I need with [date], [assignment], etc. and pop the data being read into an array. mydata$(1) = MID$(a$, INSTR(a$, "[assignment]") + 2) would store "Math 101" for me to view when everything else I need from this file has been pulled.
A second, and more organized method, requires you know the number of elements per record. In the above example, we have 5, name, date, assignment, grade, comments. If that just keeps getting repeated, you don't need any labeling to identify the entries. You identify them by numbers 1 - 5. Of course if we had 19 other students this one assignment would be 100 entries. This is where MOD comes in...
If this is per class, you might be dealing with 600 assignments * 20 students * 5 entries 60,000 lines of data. QB64 ...FOR BINARY can read a file of that size fast enough without the complexity of hashing or indexing. I have many around 40,000 that process just fine, but if you were to make a database for every student in the whole school for every school year for the next 20 years, you'd need more of the mySQL method.
Anyway. My advice would be to figure out what database format you want; a fixed block like the example above, or one with flexibility to add stuff as you go like the other example. Once you're settled on something, write a very small test database and post it if you have any questions.
Good luck,
Pete
OPEN "MYFILE.DAT" FOR INPUT AS #1
DO
LINE INPUT #1, a$
LOOP UNTIL EOF(1)
CLOSE #1
we do...
OPEN "MYFILE.DAT" FOR BINARY AS #1
DO
LINE INPUT #1, a$
LOOP UNTIL EOF(1)
CLOSE #1
Now a couple of things to note here:
1) ...FOR INPUT won't create a non-existing file, but FOR BINARY will.
2) An empty ...FOR INPUT file will just exit the loop. An empty ...FOR BINARY will error out.
So here is how to bullet proof the ...FOR BINARY method:
Code: (Select All)
IF _FILEEXISTS("MYFILE.DAT") THEN
OPEN "MYFILE.DAT" FOR BINARY AS #1
IF LOF(1) THEN ' Checks to see if there is any bytes of data in the file. Zero means it is empty, false, so the condition gets bypassed.
DO
LINE INPUT #1, a$
LOOP UNTIL EOF(1) ' End of file
END IF
CLOSE #1
END IF
I've made use of sequential files that can overwrite data so I'm just as happy using them as random access, and I don't have to be concerned about record numbers or the length of the records. Overwriting is a bit more involved in sequential files, as it requires writing to a temp file. Basically write all data up to the block you are hanging to the temp file then write the changed data then write the remaining data. Now just kill the original database file and name the temp file as the database file.
I've worked with sequential files using an "EOR" as my made up End of record marker. The structure is pretty much what Steve described. Nice in that I could put whatever I wanted into each labeled record. In other words, no pattern required, very flexible so I don't need a structure. All I did to find what I wanted out of file was add an identifier to the line of data then parse it out while line inputting it...
[name] Clippy
[date] 01-01-2000
[assignment] Math 101
[grade] F
[comments] Clippy is an idiot.
[EOR]
Now it doesn't even matter if I do the next record in this order, I can search what I need with [date], [assignment], etc. and pop the data being read into an array. mydata$(1) = MID$(a$, INSTR(a$, "[assignment]") + 2) would store "Math 101" for me to view when everything else I need from this file has been pulled.
A second, and more organized method, requires you know the number of elements per record. In the above example, we have 5, name, date, assignment, grade, comments. If that just keeps getting repeated, you don't need any labeling to identify the entries. You identify them by numbers 1 - 5. Of course if we had 19 other students this one assignment would be 100 entries. This is where MOD comes in...
Code: (Select All)
IF _FILEEXISTS("MYFILE.DAT") THEN
OPEN "MYFILE.DAT" FOR BINARY AS #1
IF LOF(1) THEN
DO
i = i + 1 'Counter
LINE INPUT #1, a$
j = i mod 5: IF j = 0 THEN j = 5 ' last record in the list of 5.
IF j = 3 THEN PRINT j, a$ ' Let's just print the assignment.
LOOP UNTIL EOF(1) ' End of file
END IF
CLOSE #1
END IF
If this is per class, you might be dealing with 600 assignments * 20 students * 5 entries 60,000 lines of data. QB64 ...FOR BINARY can read a file of that size fast enough without the complexity of hashing or indexing. I have many around 40,000 that process just fine, but if you were to make a database for every student in the whole school for every school year for the next 20 years, you'd need more of the mySQL method.
Anyway. My advice would be to figure out what database format you want; a fixed block like the example above, or one with flexibility to add stuff as you go like the other example. Once you're settled on something, write a very small test database and post it if you have any questions.
Good luck,
Pete