Microsoft KB Archive/41152
Article ID: 41152
Article Last Modified on 11/21/2006
- Microsoft QuickBasic 3.0
- Microsoft QuickBasic 4.0
- Microsoft QuickBASIC 4.0b
- Microsoft QuickBasic 4.5 for MS-DOS
- Microsoft BASIC Compiler 6.0
- Microsoft BASIC Compiler 6.0b
This article was previously published under Q41152
Records written to disk may be lost when the same random file is opened with more than one file handle at once.
There are four possible workarounds for this problem, as follows:
- Install the MS-DOS SHARE.EXE utility prior to running the Basic program.
- Use a user-defined TYPE variable to define the buffer for writing instead of using a FIELD statement. The user-defined TYPE variable must be written to the file as the third argument of the PUT statement.
- QuickBasic Version 3.00 (or earlier) does not have the user-defined TYPE option or the third argument of the PUT statement; therefore, it cannot use workaround 2 above. An alternative is to OPEN the file under just one file number, write the LAST record, CLOSE the file, and then reOPEN it with the multiple handles.
Open a given file under only one file number at once. Few, if any, programs actually need different file numbers opened at once for the same file. Note that you can use multiple FIELD statements for the same file number as long as the FIELDed variable names are distinct. The following is an example:
FIELD#1, 5 AS X$, 5 AS Y$ FIELD#1, 10 AS Z$
Microsoft has confirmed this to be a bug in QuickBasic Versions 3.00, 4.00, 4.00b, and 4.50 and Microsoft Basic Compiler Versions 6.00 and 6.00b for MS- DOS and OS/2 (buglist6.00, buglist6.00b). We are researching this problem and will post new information here in the Microsoft Knowledge Base as it becomes available.
The problem occurs when you have the same random file open several times at once under different file numbers and you use the FIELD statement to define the file buffers.
Some or all of the records written to all but the last file handle may be lost, depending on the following criteria (where the "last" file handle is defined as being the file handle that is opened last in the program and is used to write a record):
- If the file does not exist when it is opened, only records written using the last file handle are saved.
- If the file already has records when it is opened, records written using all but the last file handle will be lost if they are written beyond the existing records. However, any records written over existing records will be saved.
- If the file already has records when it is opened, and a record is written beyond the last existing record using the last file handle, this record becomes the effective end of file. Any records written up to this effective end of file will be saved. The effective end of file can be created at any point during program execution and any records written to the file previously in the program or after will be saved.
For example, a program opens the file "test.dat" as file handles #1, #2, and #3 in that order. There is only one record in the file when it initially opened. Records 1-40 are written using file handle #2, then records 41-75 are written using file handle #1. If record number 76 is then written out using file handle #3, all the records written (1-76) will be saved. If record number 20 is written out by file handle #3, only records 1-20 will be saved. Because file handle #3 was the last one opened, it controls the effective end of file.
The following is an example program that opens the file "test.dat" using four different file handles. It writes out 150 records using file handle 1, and the next 150 records using file handle 2. It then writes out record number 7 using file handle 3 and closes the file. It then reopens the file, reads a record, then uses the DOS TYPE command to print the contents of the file. It only prints out seven records. Although file handle 4 is opened last, it has no effect on which records are saved to disk because no record is written using this handle.
The following is a source code:
CLS SHELL "del test2.dat" OPEN "test2.dat" FOR RANDOM AS #1 LEN = 52 FIELD #1, 25 AS lastname1$ LSET lastname1$ = "test record" PUT #1, 1 CLOSE OPEN "test2.dat" FOR RANDOM AS #1 LEN = 52 OPEN "test2.dat" FOR RANDOM AS #2 LEN = 52 OPEN "test2.dat" FOR RANDOM AS #3 LEN = 52 OPEN "test2.dat" FOR RANDOM AS #4 LEN = 52 FIELD #1, 25 AS lastname1$, 15 AS firstname1$, 12 AS ssn1$ FIELD #2, 25 AS lastname2$, 15 AS firstname2$, 12 AS ssn2$ FIELD #3, 25 AS lastname3$, 15 AS firstname3$, 12 AS ssn3$ FIELD #4, 25 AS lastname4$, 15 AS firstname4$, 12 AS ssn4$ LSET lastname1$ = "Doe1" LSET firstname1$ = "John" LSET ssn1$ = "111-22-3333" LSET lastname2$ = "Doe2" LSET firstname2$ = "John" LSET ssn2$ = "111-22-3333" LSET lastname3$ = "Doe3" LSET firstname3$ = "John" LSET ssn3$ = "111-22-3333" FOR i = 1 TO 150 PUT #1, i NEXT i FOR i = 151 TO 300 PUT #2, i NEXT i PUT #3, 7 CLOSE OPEN "test2.dat" FOR RANDOM AS #1 LEN = 52 FIELD #1, 25 AS lastname$ GET #1, 30 PRINT lastname$ CLOSE SHELL "type test2.dat" In the program example shown below, the correct information is written to records 2 and 4, but not to records 1 and 3. The results are as if the FIELD #1 statement had no effect. The following is the source code: CLS KILL "test.dat" OPEN "test.dat" FOR RANDOM AS #1 LEN = 10 ' Add following code as work around (such as for QuickBasic 3.00), ' where you would set n equal to the largest file to be written: ' FIELD #1, 10 as a$ ' LSET a$="" ' n=10 ' PUT #1,n CLOSE #1 OPEN "test.dat" FOR RANDOM AS #1 LEN = 10 OPEN "test.dat" FOR RANDOM AS #2 LEN = 10 FIELD #1, 10 AS a$ FIELD #2, 10 AS b$ LSET a$ = "firstpart" PUT #1, 1 LSET b$ = "second" PUT #2, 2 LSET a$ = "third" PUT #1, 3 LSET b$ = "fourth" PUT #2, 4 CLOSE OPEN "test.dat" FOR RANDOM AS #1 LEN = 10 FIELD #1, 10 AS a$ GET #1, 1 PRINT a$ GET #1, 2 PRINT a$ GET #1, 3 PRINT a$ GET #1, 4 PRINT a$
Additional query words: QuickBas BasicCom buglist3.00 buglist4.00 buglist4.00b buglist4.50