Using Files: Section IV
This section teaches you how to work with files in other modes than Input and Append, and shows you how user defined types can be stored in files. You will also learn how to work with binary files.
Author: Jens G. Balchen

Before You Start

You should know what a user defined type is and how it works. Reading sections I-III won't hurt.

Two Other File Modes

There are two other file modes that are useful, Binary and Random. They are not what they seem (especially Random could have been named differently).

Binary

In Binary access, you read raw bytes. You can one byte at a time, or you can read them in groups. Both carriage return and line feed are bytes -- they will be read like every other byte in the file.

Binary access is mostly used when you read or write files that aren't to be read by humans. The result will mostly be unreadable, unless you purposely insert line feeds and other formatting elements in the file. You can write any byte to a Binary file, not just the printable one. Escape, for instance, has ASCII value 27, and can be written to a Binary file.

Bytes are read or written by their absolute position in the file, with the first byte being number 1.

Code to open a file as Binary:

   Open "C:\Windows\My File.txt" For Binary As #1

Random

Random access should have been called Record access. It allows you to view a file as a list of records. You define the record length (in bytes), and then specify a record index instead of a position. Other than that, it works as the Binary access mode.

Code to open a file as Random:

   Open "C:\Windows\My File.txt" For Random As #1 Len = n

where n is the length of one record in bytes.

Reading And Writing Binary Files

For Binary and Random access files, the Input and Line Input commands don't work. Visual Basic uses the Get and Put commands instead. They work like this:

   Get #file handlepositionData
   Put #file handlepositionData

If you wish, you can skip the position argument. The commands will continue to read/write from the current position in the file, but you will have to include the commas:

   Get #file handle, , Data
   Put #file handle, , Data

The commands use the length of Data to determine how many bytes to read or write. Since strings are usually variable-length in Visual Basic, this could be a problem. The easiest way out is to specify a fixed length to your strings, like this:

   Dim Data As String * n

where n is the length of the string. This way, Visual Basic will read or write n bytes.

Binary files can be difficult to create yourself, since Notepad and almost all other editors are text editors. You can test the code to read from a binary file, however, on an ordinary text file. The code goes like this:

   Dim Data As String * 12

   Open "C:\Windows\My File.txt" For Binary As #1
      Get #1, 1, Data
      Debug.Print Data
   Close #1

The code will read the 12 first bytes in the file and print them to the Debug Window. If your file is shorter than 12 bytes, you will see that you get some black squares after the real data. This is because Visual Basic pads the string with enough blank characters to fill 12 bytes.

If you want to write to a file, the procedure is the same, but you need to be aware of one thing: Visual Basic doesn't like it if you specify the data to write as a string directly. It prefers you first store the string in a variable, and then use the Put command with the variable as a parameter.

   Dim Data As String * 12

   Open "C:\Windows\My File.txt" For Binary As #1
      Data = "This is 12 b"
      Put #1, 1, Data
   Close #1

If the file exists, the first 12 bytes will be replaced with "This is 12 b".

Using User Defined Types

A user defined type is excellent when working with binary files, since a UDT (short for user defined...) is made up of fixed-length data. Variable-length strings shouldn't be used in a UDT, only fixed-length strings and numeric data types.

There is no difference between UDTs and strings when you use the Get and Put commands. All the same rules apply: the length of the UDT determines how many bytes Visual Basic reads.

Here's a quick sample with a UDT you will recognize from section II and records:

' This code must be placed in the Declarations section of a form or module
Private Type Person
   Firstname As String * 20
   Lastname As String * 20
   Age As String * 2
End Type

   Dim Data As Person

   Open "C:\Windows\My File.txt" For Binary As #1
      Get #1, 1, Data
   Close #1

As you have probably noticed, the length of Person is 42 bytes. The Get command will read 42 bytes from the text file and place it in Data, no matter what the bytes are. If you use the Debug Window and do a Debug.Print Data.Firstname, you will see what the first 20 bytes in the file were. Data.Lastname contains the next 20 bytes, and Data.Age the next two.

If you want to write, the procedure is the same as before. No need to repeat that, I hope.

Working With Random Files

I explained UDTs before random files because of the tight link between them. A UDT is a record, and random access mode is designed to read records. The procedure it very like that of binary mode, except you don't give a position, you give a record number. So the line

      Get #1, 1, Data

means "Get me record number 1". When you open a file for random access, you define a record length. In the case of UDTs, it would be the length of the UDT. Like binary access, the file is difficult to create by hand, since most text-editors use the line-by-line principle. I've prepared a random access file for you that will fit with the next sample.

Download

Unless you want to download it to a specific place, create a folder called C:\Samples and store it there.

' This code must be placed in the Declarations section of a form or module
Private Type Person
   Firstname As String * 20
   Lastname As String * 20
   Age As String * 2
End Type

   Dim Data As Person

   Open "C:\Samples\Random.txt" For Random As #1 Len = 42
      Get #1, 1, Data
   Close #1

A Debug Window examination of Data will hopefully reveal some information on Tom Jones (legendary pop singer).

If you want to read records 2 and 3, the procedure is the same. For unknown record numbers, here's a trick:

   NumRecords = LOF(1) / record length

LOF means Length of File, and takes a file handle as a parameter. It works on open files just as EOF. When you know the number of records, you can use a For...Next structure to read the entire file, like this:

   Dim Data As Person
   Dim Counter As Long

   Open "C:\Samples\Random.txt" For Random As #1 Len = 42
      For Counter = 1 To LOF(1) / 42
         Get #1, CounterData
         ' Do a Debug.Print here if you like
      Next Counter
   Close #1

In this entire section, I have paid no attention to reading and writing in Do...Loop structure. The procedure is equal to that in Section II, so I see no need to explain it again.

Next Section

In Section V, we will look at some advanced options for binary mode file editing.