Random Access Files
Visual Basic .Net allows random access to files using StreamReader class. The file pointer can be set as required, and data can be read or written as a stream of bytes or as a nominated variable type.
Random access file processing involves positioning the file pointer to an absolute position within the file, and then reading data from that file position. The data is typically organised as fixed length records (and can often be read as a single structure), but random file access is also required for some variable length record structures, where the file position of a record is maintained in an index or as part of a linked list of records.
Random access is implemented with a stream and a reader – these examples will use a binary reader. The stream object supports absolute positioning within the file, while the binary reader allows reading a string or byte array of nominated size, or a specific variable type, such as integer, double, or structure.
The following code example positions the file pointer to position ptr, and reads a string of 28 characters followed by two doubles. Note that, as with any string processing, the actual results will depend on the current encoding. A byte array would actually be preferable to a string if the fixed length string of 28 characters is actually a sequence of 28 bytes that happen to represent ASCII characters – the byte array avoids any issues of encoding and multi-byte characters.
Dim sr As System.IO.Stream = System.IO.File.Open( _ "Random.DAT", System.IO.FileMode.Open, _ System.IO.FileAccess.Read, System.IO.FileShare.Read) Dim reader As New System.IO.BinaryReader( _ sr, System.Text.Encoding.ASCII) Dim ptr As Long '... ptr = RecordNumber * RecordSize '... Dim Model As String Dim QIS As Double Dim QOO As Double reader.BaseStream.Seek(ptr, System.IO.SeekOrigin.Begin) Model = New String(reader.ReadChars(28), 0, 28) QIS = reader.ReadDouble QOO = reader.ReadDouble '... reader.Close() sr.Close()
The Binary Reader Read… methods all advance the file pointer to the next byte, so only one positioning statement is required per record, unless you are reading randomly within the record.
To use this for variable length records, it is usually necessary to get the record length first. In this example the record length is stored as an integer at the start of each record, followed by the variable length byte array. This is a common arrangement for variable length records, and has the advantage the the file pointer is already positioned at the start of the record data after the record length has been read.
Dim sr As System.IO.Stream = System.IO.File.Open( _ "VarByte.DAT", System.IO.FileMode.Open, _ System.IO.FileAccess.Read, System.IO.FileShare.Read) Dim reader As New System.IO.BinaryReader( _ sr, System.Text.Encoding.ASCII) reader.BaseStream.Seek(0, System.IO.SeekOrigin.Begin) Do until (reader.BaseStream.Position = reader.BaseStream.Length) Dim RecSize As Integer = reader.ReadInt32 Dim B() As Byte = reader.ReadBytes(RecSize) 'No positionng required ' Process the B array Loop '... reader.Close() sr.Close()
The other possibility is that the records are separated by a record marker. The processing for that type of file would involve reading a byte at a time, assembling the byte array, until the EoR marker is detected.