Imports System.IO

Public Class clsList

  ' Set the length for each data field
  Private Const FIRST_NAME_LENGTH As Integer = 10
  Private Const LAST_NAME_LENGTH As Integer = 20
  Private Const ADDR_LENGTH As Integer = 30
  Private Const CITY_LENGTH As Integer = 15
  Private Const STATE_LENGTH As Integer = 2
  Private Const ZIP_LENGTH As Integer = 10

  ' ====================== Data members ======================== 
  ' Calculate record size
  Private mRecordSize As Long = FIRST_NAME_LENGTH + _
                              LAST_NAME_LENGTH + _
                              ADDR_LENGTH + CITY_LENGTH + _
                              STATE_LENGTH + ZIP_LENGTH

  Private mFirst(FIRST_NAME_LENGTH) As Char     ' The actual field data
  Private mLast(LAST_NAME_LENGTH) As Char
  Private mAddr(ADDR_LENGTH) As Char
  Private mCity(CITY_LENGTH) As Char
  Private mState(STATE_LENGTH) As Char
  Private mZip(ZIP_LENGTH) As Char


  Private mFileName As String     ' Name of data file
  Private mCurrentRecord As Long      ' The current record number
  Private mCurrentRecordCount As Long ' How many records in the file

  ' =============== Working variables ==================
  Private Len As Integer
  Private buff As String

  ' =================== Properties =====================
  Public Property First() As String           ' First Name
    Get
      Return mFirst
    End Get
    Set(ByVal Value As String)
      Len = Value.Length
      If Len <= FIRST_NAME_LENGTH Then
        buff = Value & Space(FIRST_NAME_LENGTH - Len)
      Else
        buff = Value.Substring(0, FIRST_NAME_LENGTH)
      End If
      mFirst = buff.ToCharArray()
    End Set
  End Property

  Public Property Last() As String            ' Last name
    Get
      Return mLast
    End Get
    Set(ByVal Value As String)
      Len = Value.Length
      If Len <= LAST_NAME_LENGTH Then
        buff = Value & Space(LAST_NAME_LENGTH - Len)
      Else
        buff = Value.Substring(0, LAST_NAME_LENGTH)
      End If
      mLast = buff.ToCharArray()
    End Set
  End Property

  Public Property Addr() As String            ' Street address
    Get
      Return mAddr
    End Get
    Set(ByVal Value As String)
      Len = Value.Length
      If Len <= ADDR_LENGTH Then
        buff = Value & Space(ADDR_LENGTH - Len)
      Else
        buff = Value.Substring(0, ADDR_LENGTH)
      End If
      mAddr = buff.ToCharArray()
    End Set
  End Property

  Public Property City() As String            ' City
    Get
      Return mCity
    End Get
    Set(ByVal Value As String)
      Len = Value.Length
      If Len <= CITY_LENGTH Then
        buff = Value & Space(CITY_LENGTH - Len)
      Else
        buff = Value.Substring(0, CITY_LENGTH)
      End If
      mCity = buff.ToCharArray()
    End Set
  End Property

  Public Property State() As String           ' State
    Get
      Return mState
    End Get
    Set(ByVal Value As String)
      Len = Value.Length
      If Len <= STATE_LENGTH Then
        buff = Value & Space(STATE_LENGTH - Len)
      Else
        buff = Value.Substring(0, STATE_LENGTH)
      End If
      mState = buff.ToCharArray()
    End Set
  End Property

  Public Property Zip() As String             ' Zip Code
    Get
      Return mZip
    End Get
    Set(ByVal Value As String)
      Len = Value.Length
      If Len <= ZIP_LENGTH Then
        buff = Value & Space(ZIP_LENGTH - Len)
      Else
        buff = Value.Substring(0, ZIP_LENGTH)
      End If
      mZip = buff.ToCharArray()
    End Set
  End Property

  Public Property FileName() As String        ' File name
    Get
      Return mFileName
    End Get
    Set(ByVal Value As String)
      mFileName = Value
    End Set
  End Property

  Public ReadOnly Property RecordSize() As Long         ' record size
    ' ReadOnly because user should never change this
    Get
      Return mRecordSize
    End Get
  End Property

  Public ReadOnly Property CurrentRecordCount() As Long ' record count
    ' ReadOnly because user should never change this
    Get
      If mCurrentRecordCount = 0 Then
        GetRecordCount()
      End If
      Return mCurrentRecordCount
    End Get
  End Property

  ' ===================== Methods ===================
  Public Function WriteRecord(ByVal ThisRecord As Integer) As Integer
    ' Purpose: To write a random record
    '
    ' Argument list:
    '   ThisRecord      the record number to write
    '
    ' Return value:
    '   integer         0 if OK, 1 on error

    Dim ErrorFlag As Integer
    Dim MyFile As FileStream
    Dim MyBinaryObject As BinaryWriter

    Try         ' Set things up to write a record
      MyFile = New FileStream(mFileName, FileMode.Open, FileAccess.Write)
      MyBinaryObject = New BinaryWriter(MyFile)
      MyFile.Position = (ThisRecord - 1) * mRecordSize
      MyBinaryObject.Write(mFirst)
      MyBinaryObject.Write(mLast)
      MyBinaryObject.Write(mAddr)
      MyBinaryObject.Write(mCity)
      MyBinaryObject.Write(mState)
      MyBinaryObject.Write(mZip)
      MyFile.Close()
      MyFile = Nothing
      MyBinaryObject = Nothing
      mCurrentRecordCount += 1      ' Up the record counter
    Catch
      MessageBox.Show("Something went wrong in WriteRecord().", "I/O Error")
      ErrorFlag = 1
    End Try
  End Function

  Public Function ReadRecord(ByVal ThisRecord As Integer) As Integer
    ' Purpose: To read a random record and fill in members
    '
    ' Argument list:
    '   ThisRecord      the record number to read
    '
    ' Return value:
    '   integer         0 if OK, 1 on error

    Dim ErrorFlag As Integer
    Dim MyFile As FileStream
    Dim MyBinaryObject As BinaryReader

    Try
      MyFile = New FileStream(mFileName, FileMode.Open, FileAccess.Read)
      MyBinaryObject = New BinaryReader(MyFile)
      MyFile.Seek((ThisRecord - 1) * mRecordSize, SeekOrigin.Begin)
      mFirst = CStr(MyBinaryObject.ReadChars(FIRST_NAME_LENGTH))
      mLast = CStr(MyBinaryObject.ReadChars(LAST_NAME_LENGTH))
      mAddr = CStr(MyBinaryObject.ReadChars(ADDR_LENGTH))
      mCity = CStr(MyBinaryObject.ReadChars(CITY_LENGTH))
      mState = CStr(MyBinaryObject.ReadChars(STATE_LENGTH))
      mZip = CStr(MyBinaryObject.ReadChars(ZIP_LENGTH))
      MyFile.Close()
      MyFile = Nothing
      MyBinaryObject = Nothing
    Catch
      MessageBox.Show("Read error in ReadRecord()", "I/O Error")
      ErrorFlag = 1
    End Try
    Return ErrorFlag
  End Function

  ' ===================== Helpers ===================

  Private Sub GetRecordCount()

    Try
      If mFileName.Length <> 0 Then             ' Find out how many records
        mCurrentRecordCount = FileLen(mFileName) / mRecordSize
      End If
    Catch fileexception As FileNotFoundException    ' If a new file
      Dim MyFile As FileStream = New FileStream(mFileName, FileMode.Create, FileAccess.ReadWrite)
      MyFile.Close()
      MyFile = Nothing
      mCurrentRecordCount = 0
    End Try

  End Sub

End Class
