Imports System.IO
Public Class clsList

  ' Ustawiamy długość każdego pola danych
  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

  ' ====================== Składniki danych ======================== 

  ' Oblicza długość rekordu, czyli aktualnie 87 bajtów
  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     ' Aktualne pole danych 
  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            ' Nazwa pliku danych
  Private mCurrentRecord As Long         ' Numer bieżącego rekordu 
  Private mCurrentRecordCount As Long    ' Rekordy w pliku

  Private Len As Integer                 ' Zmienne robocze 
  Private buff As String

  ' =================== Właściwości =====================

  Public Property First() As String      ' Imię
    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      ' Nazwisko
    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      ' Adres
    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      ' Miasto
    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      ' Stan
    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       ' Kod pocztowy
    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    ' Nazwa pliku
    Get
      Return mFileName
    End Get
    Set(ByVal Value As String)
      mFileName = Value
    End Set
  End Property

  Public ReadOnly Property RecordSize() As Long     ' Rozmiar rekordu
    ' ReadOnly ponieważ użytkownik nigdy nie powinien go zmieniać
    Get
      Return mRecordSize
    End Get
  End Property

  Public ReadOnly Property CurrentRecordCount() As Long ' Licznik rekordów 
    'ReadOnly ponieważ użytkownik nigdy nie powinien go zmieniać
    Get
      If mCurrentRecordCount = 0 Then
        GetRecordCount()
      End If
      Return mCurrentRecordCount
    End Get
  End Property

  ' ===================== Metody ===================

  Public Function WriteRecord(ByVal ThisRecord As Integer) As Integer
    ' Cel: zapisać rekord o dostępie swobodnym
    '
    ' Lista argumentów:
    '  ThisRecord   numer rekordu do napisania
    '
    ' Zwracana wartość:
    '  integer     0 jeśli OK, 1 dla błędu

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

    Try     ' Inicjuje zapis rekordu 
      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   ' Powiększa licznik rekordów
    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
    ' Cel: przeczytać rekord o dostępie swobodnym i wypełnić składniki
    '
    ' Lista argumentów:
    '  ThisRecord   numer rekordu do przeczytania
    '
    ' Return value:
    '  integer     0 jeśli OK, 1 dla błędu

    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

  ' ===================== Programy pomocnicze ===================

  Private Sub GetRecordCount()

    Try
      If mFileName.Length <> 0 Then       ' Sprawdź, ile rekordów
        mCurrentRecordCount = FileLen(mFileName) / mRecordSize
      End If
    Catch fileexception As FileNotFoundException  ' Jeśli nowy plik
      Dim MyFile As FileStream = New FileStream(mFileName, _
                FileMode.Create, FileAccess.ReadWrite)
      MyFile.Close()
      MyFile = Nothing
      mCurrentRecordCount = 0
    End Try

  End Sub

End Class
