Except as a pipe specification (see below), FileSpec is taken as a UNIX filename which may specify either an ordinary disk file or a tty file. A tty file is a special UNIX file which actually refers a communication channel for a terminal. If FileSpec does not refer to a pre-existent tty, it taken as a disk file. Thus if FileSpec does not refer to an existing file, implying the file needs to be created, it is created as a disk file.
If FileSpec is of the form "PIPE: command", a pipe is established to the UNIX command given. The command is executed as if it were typed at the terminal using the UNIX shell sh. A pipe is a direct communication channel to a similar channel of another program. From the point of view of the BASIC program, output to the pipe is sent directly to the standard input of the command and input from the pipe is received directly from the standard output of the command.
In the first form of the open statement, Mode specifies the method of
access and is among the following:
Mode | Method of Access | ||||
input | sequential input only | ||||
output | sequential output only | ||||
append | sequential output only, appending | ||||
random | random access or sequential bidirectional I/O |
If Mode is omitted, random is assumed.
In the second form of the open statement, Mode2 specifies the method of access and is a string expression, the first character of which must match the first character of one of the Modes listed in the table above.
Opening a file for input only forbids subsequent writing. Opening a file for output only forbids subsequent reading. No such restriction exists for bidirectional I/O. If FileSpec refers to a file that does not exist, it is created unless the file is to be open for input only.
Appending is the same as ordinary outputting for tty’s and pipes. For disk files, appending means that subsequent writing will extend the file without disturbing the original initial portion. Outputting without appending means that writing begins at the beginning of the file and the original portion of the file is lost. A simpler view of appending may be to view not appending as the special case where the file is initially truncated to empty. Thereafter, whether appending or not, writing will extend the file from its end.
Opening a disk file for random indicates the special random access bidirectional mode. In general, all input and output is performed sequentially and directly to a file. Random I/O is the exception. Random I/O introduces a (user accessible) buffer between the sequential I/O statements and the file. The get and put statements are used to explicitly read and write the buffer to the file. The buffer may be read or written to any location within the file at any time providing random access. Within the buffer, I/O may be performed sequentially. More commonly however, fields are set up within the buffer (see field) and these fields are manipulated as strings facilitated by the lset and rset statements. The length of the buffer in bytes is given by Len. Len is interpreted as an unsigned integer: a negative Len yields a buffer length of 65536 - Len. If Len is omitted, 128 is assumed.
If a tty is open for input, Len is the number of seconds to wait for input before giving up on a read attempt. If Len is omitted, the program will wait forever if necessary.
a$ = "Basmark Corporation" ? "Sequential Files -- Using Form 1:" ? ? "1. OPEN FileSpec [FOR Mode] AS FileNum " open "s1" for output as 1 write #1, a$ close #1 ? "2. OPEN FileSpec [FOR Mode] AS [#] FileNum " open "s2" for output as #1 write #1, a$ close #1 ? "Sequential Files -- Using Form 2:" ? ? "3. OPEN Mode2, FileNum, FileSpec " open "O", 1, "s3" write #1, a$ close #1 ? "4. OPEN Mode2, [#]FileNum, FileSpec " open "O", #1, "s4" write #1, a$ close #1Any pre-existing data in the files will be destroyed (open with append to avoid data destruction):
? "5. Define File and Open for Append" file$ = "s5" open file$ for append as 1 write #1, a$ close #1The example above illustrates an indirect FileSpec. The next example opens the file "s5" and positions the file pointers so that any output to the file is placed at the end of existing data in the file. The following statements open files named "r6" through "r9" for random output.
a$ = "Basmark Corporation" ? "Random Access Files -- Using Form 1:" ? ? "6. OPEN FileSpec AS FileNum [LEN = Recl]" open "r6" as 1 len = 120 for i = 40 to 120 step 40 field #1, i as n$ lset n$ = a$ put #1, i next i close #1 ? "7. OPEN FileSpec AS FileNum " open "r7" as 1 field #1, 40 as n$ rset n$ = a$ put #1 close #1 ? "Random Access Files -- Using Form 2:" ? ? "8. OPEN Mode2, FileNum, FileSpec [,Recl]" open "R", 1, "r8", 80 field #1, 40 as n$ rset n$ = a$ put #1 close #1 ? "9. OPEN Mode2, [#]FileNum, FileSpec [,Recl]" open "R", #1, "r9", 80 field #1, 40 as n$ lset n$ = a$ put #1 close #1The following example illustrates the use of pipes both for input and output. The purpose of this program is to request the name of a user on the system, determine if the user is logged in and sent the user a greeting.
10 on error goto 500 20 input "Who are you looking for"; user$ 30 open "PIPE: who | grep "+user$ for input as #1 40 line input #1, who$ 50 close #1 60 print who$ 70 open "PIPE: write "+user$ for output as #1 80 print #1, "Tally-ho!" 90 print #1, "Greetings and Felicitations!" 100 close #1 110 end 500 if erl <> 40 then on error goto 0 510 print "Sorry, " user$ " isn't logged in." 520 close #1 530 resume 110When executed, the output might look like this:
Who are you looking for? ljl ljl console Aug 18 17:40The name of the user is requested and the name is stored in user$. Next, on line 30, a "file" is open for input which is the output piped from a command, in this case, "who | grep ljl." The output of the UNIX program "who" is piped to the UNIX pattern matching program "grep," in this case, the pattern is "ljl" and the matching line appears on standard output which is piped to the BASIC program as file number one. On line 40, the line is read in. If the user had not been logged in, no line would be available and a error condition would cause the error handling routine at line 500 to be executed. The error routine would report the anomaly and exit gracefully. Normally, however, the login entry is printed and the pipe is closed. Then, on line 70, another pipe is opened, this time for output. The command in this case is "write ljl" with its standard input attached to file number one. The greeting is written to this file number and thus piped to the UNIX program "write" which prints it on the user’s terminal.
The final example demonstrates opening another terminal (other than the terminal on which the program is invoked):
open "/dev/tty11" as #1 print #1, "Welcome to the Game of Stellar" input #1, "How many stars do you want"; a print #1, string$(a, "*") close #1"/dev/tty11" refers to a terminal that is not set up for logging in. Permission to read and write the terminal is also necessary. If the user responds with "10", the output on "/dev/tty11" would be:
Welcome to the Game of Stellar How many stars do you want? 10 **********
If Mode2 does not begin with an appropriate character, a "Bad file mode" error occurs.
If an attempt is made to open a nonexistent file for input, a "File not found" error occurs.
If FileNum is already open, a "File already open" error occurs.
A buffer used for random I/O is never deallocated even after the file has been closed in order to prevent fielded strings from being corrupted. If the same FileNum is used for random I/O again and the old buffer is large enough, the buffer is reused. Otherwise a new buffer is allocated and the old buffer is lost forever. If memory space is a premium, opening the FileNum with the largest buffer first is efficient.
Note that it is possible to have a single UNIX file open several times at once, using different file numbers and different modes. Care should be taken when writing a given file specification using one file number and reading it using another.
A limit exists for the maximum number of UNIX files that may be open at once by a single program. In practice, this limit is large (about 15).
There is very little to recommend bidirectional pipes. The possibilities for deadlock are legion. If at all possible, it is probably wisest to open the pipe for output only and send the process’s output to a temporary file; then open the file for input and read it in.
Basmark QuickBASIC adopts UNIX file naming conventions.
from The Basmark QuickBASIC Programmer’s Manual by Lawrence Leinweber