Every file is either "open" (being used) or "closed" (currently unused). To open a file in Visual Basic, use the following command in code:
Open filename For mode As #filenumber
The above statement will be explained in more detail later. To close all open files, use the CLOSE command:
Close
To close a particular file, use its filenumber (e.g. Close 1).
Sequential Files
With sequential files, the contents of variables are dumped into a file in a formatted fashion. There are three modes you can use when you open a sequential file, "Input" (you plan to read data from the file into variables, starting at the beginning of the file), "Output" (you plan to write data from variables to the file, starting at the beginning of the file), and "Append" (you plan to write data from variables to the file, starting at the end of the file).
The command you use to read data from a file is "Input":
Input #filenumber, variable1, variable2, variable3 . . .
The command used to write data to a file is "Write":
Write #filenumber, variable1, variable2, variable3 . . .
So let's say you have a program that reads a person's name, address, and zip code into three variables: name$ (a string variable), address$ (another string variable), and ZipCode (a numeric variable). Then you click on a command button to write that data to a file named foo.dat:
Private Sub Command1_Click() Open "foo.dat" For Output As 1 Write #1, name$, address$, ZipCode Close End Sub
Another command button reads in the data from foo.dat into the appropriate variables:
Private Sub Command2_Click() Open "foo.dat" For Input As 1 Input #1, name$, address$, ZipCode Close End Sub
To understand what the data file would look like, imagine a user had run your program and entered the following information: name "Bill Clinton", address "1600 Pennsylvania Avenue", and zip code 10254. The file foo.dat would look like this:
"Bill Cinton","1600 Pennsylvania Avenue",10254
To some programmers, this is somewhat sloppy. It's also inconvenient, since if you wanted to change the 128th record, you'd have to read in all the records, change the 128th, then write them all back out to the file. To relieve these problems, another way of accessing files was invented, called:
Random-Access Files
This is actually something of a misnomer; it's not really random. Anyway, the format for Open is somewhat different:
Open filename For Random As #filenumber Len=recordlength
Random-access files can be read to and written from without having to be closed and opened, so we don't have to worry about that. The recordlength refers to the length of a record, and to understand this we have to understand Types.
A Type is essentially a collection of variables. Here's an example of a type:
Type Info name As String * 20 address As String * 50 city as String * 20 state As String * 2 zip As Integer ' 2 bytes End Type
Thus, Info is a collection of 5 string and numeric variables. You ask, "Why the * 20's?" Those indicate the actual size (in bytes) of each of the variables. name, for example, is a string containing 20 bytes worth of information (20 characters' worth). The comment saying "2 bytes" after the declaration of the zip variable is to remind us that Integer variables are always 2 bytes in size.
If we add up all those byte sizes, we get 94. Thus, Info takes up 94 bytes of space. If we made an array of this type, like so:
Dim xyz(1 To 100) As Info
We would have an array of types, each of those types containing 94 bytes of data. I'm sure you can see why this would be useful, but the neat thing is we now know exactly how much space our information is going to take up.
Now back to recordlength. recordlength refers to the length (in bytes) of each record. If we have this array of types, we know our recordlength. In this case, it's 94. Now we can actually open a random-access file (let's say, C:\data\poobah.dat):
Open "C:\data\poobah.dat" For Random As 1 Len=94
OK, so now we figure out how to access this information. To read information from a file to a variable, we use the Get command:
Get #filenumber, byteposition, variable1, variable2, variable3, . . .
You can actually leave out the byteposition and the program will just retrieve the next bunch of data, whatever fits into the variable(s).
So in our example, let's say we want to read the first three records from the file into our array (this time we're using the file C:\data\poobah.dat):
Open "C:\data\poobah.dat" For Random As 1 Len=94 Get #1, , xyz(1) Get #1, , xyz(2) Get #1, , xyz(3) Close
You get the idea? Or we could have a loop and read in the first ten records:
Open "C:\data\poobah.dat" For Random As 1 Len=94 For index = 1 To 10 Get #1, , xyz(index) Next index Close
To output data from variables to a file, you use the Put command:
Put #filenumber, byteposition, variable1, variable2, variable3, . . .
Familiar? Again, you can remove the byteposition and the program will just write to the next available space. Again, using our example, let's write all 100 records in our array to C:\data\poobah.dat:
Open "C:\data\poobah.dat" For Random As 1 Len=94 For index = 1 To 100 Put #1, , xyz(index) Next index Close
Note that you can use both Get and Put in the same Open session; you don't have to Close and re-Open the file.
One other little piece of information that might be useful: there's actually a little bit of memory that points to the current position in each file you have open. This pointer is moved every time you read from or write to a file to reflect where you are in the file. While you can't access this pointer directly, there is a function called Eof(filenumber) that returns True when this pointer hits the end of the file (and returns False the rest of the time). So, let's say you wanted to read all the information from recs.dat into your array (assuming that there's no more than 100 records in recs.dat):
Open "recs.dat" For Random As 1 Len=94 index = 0 While Not Eof(1) ' Loop while you haven't hit the end of the file index = index + 1 Get #1, , xyz(index) Wend NumberOfRecords = index ' We just read _index_ records Close
That's it! Easy enough....