Чтение из текстового файла в структуру и размещение в списках — есть ли более эффективный способ сделать это?

Я стараюсь опережать своих учеников на 12-м курсе по программному обеспечению. Приступаем к работе с записями и массивами. Я ответил на вопрос, но решение кажется очень неуклюжим. Я надеюсь, что у кого-то есть предложения / ссылки для более эффективного выполнения этой задачи. Задача: прочитать строки из текстового файла и преобразовать их в структуру, а затем перебрать ее, заполнив четыре списка, если животное не было вакцинировано. Вот код:

Imports System.IO
Public Class Form1
    'Set up the variables - customer record, total pets not vaccinated, total records in the file, and a streamreader for the file.
    Structure PetsRecord
        Dim custName As String
        Dim address As String
        Dim petType As String
        Dim vacced As String
    End Structure
    Dim totNotVac As Integer
    Dim totalRecCount As Integer
    Dim PetFile As IO.StreamReader

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    End Sub

    Private Sub btnLoad_Click(sender As Object, e As EventArgs) Handles btnLoad.Click

        'set an array of records to store each record as it comes in. Limitation: you need to know how many records in the file. Set the array at 15 to allow for adding more in later.
        Dim PetArray(15) As PetsRecord
        'variables that let me read in a line and split it into sections.
        Dim lineoftext As String
        Dim i As Integer
        Dim arytextfile() As String
        'tell them what text file to read
        PetFile = New IO.StreamReader("patients.txt")
        totNotVac = 0

        Try
            totalRecCount = 0
            ' read each line in and split the lines into fields for the records. Then assign the fields from the array. Finally, reset the array and loop.
            Do Until PetFile.Peek = -1
                'read in a line of text 
                lineoftext = PetFile.ReadLine()
                'split that line into bits separated by commas. these will go into the array.
                arytextfile = lineoftext.Split(",")
                'dunno whether this is the best way to do it, but stick the array bits into the record, and then clear the array to start again.
                PetArray(totalRecCount).custName = arytextfile(0)
                PetArray(totalRecCount).address = arytextfile(1)
                PetArray(totalRecCount).petType = arytextfile(2)
                PetArray(totalRecCount).vacced = arytextfile(3)

                totalRecCount += 1
                Array.Clear(arytextfile, 0, arytextfile.Length)
            Loop

            For i = 0 To PetArray.GetUpperBound(0)

                If PetArray(i).vacced = "No" Then
                    lstVaccinated.Items.Add(PetArray(i).vacced)
                    lstCustomer.Items.Add(PetArray(i).custName)
                    lstAddress.Items.Add(PetArray(i).address)
                    lstPetType.Items.Add(PetArray(i).petType)

                    totNotVac += 1
                    lblVacTotal.Text = "The total number of unvaccinated animals is " & CStr(totNotVac)
                End If

            Next
        Catch ex As Exception
            MsgBox("Something went wrong with the file")
        End Try
        PetFile.Close()

    End Sub

    Private Sub btnExit_Click(sender As Object, e As EventArgs) Handles btnExit.Click
        Close()

    End Sub
End Class

И одна строчка из файла Patient.txt:

    Richard Gere,16 Sunset Blvd,Gerbil,No

Надеюсь, это не к месту.

С уважением,

Дамиан

1 ответ
1

Мнение: строить такой массив бесполезно. Я согласен, что это неуклюжее использование массивов, которое я считаю ненужным (и устаревшим). Например, вам даже не нужно заранее знать, сколько записей, и вам не нужно измерять массив до заранее определенного размера. Для работы доступны более гибкие типы данных, чем массивы.

При добавлении элементов в элементы управления, например ListView или ListBox, с помощью .Items.Add вы можете использовать BeginUpdate в начале вашего цикла и EndUpdate в конце, когда вы заполняете элементы из цикла.

Цель состоит в том, чтобы сделать пользовательский интерфейс более отзывчивым — если у вас большой файл и вы добавляете много элементов, интерфейс может зависнуть во время выполнения цикла.

Хотя я бы, вероятно, вместо этого привязал список к базе данных или другой структуре. Просто добавьте элементы в таблицу данных и позвольте элементу управления обновиться.

Итак, вот отредактированный пример: я преобразовал вашу структуру в класс и использую List Of вместо массива (обратите внимание на добавление источника привязки). Чтобы это сработало, мне нужно использовать характеристики чтобы раскрыть члены класса (так я думаю), поэтому я использую класс вместо структуры, но должен быть способ сохранить структуру, если вы хотите.

Есть несколько способов чтения файла, в этом примере я использую StreamReader. Обратите внимание на использование диспетчера контекста ( Using block), а это значит, что мне не нужно беспокоиться о закрытии файла, в том числе в случае исключения. Это происходит автоматически после End Using утверждение.

В вашем коде PetFile.Close() не будет выполняться в случае возникновения исключения. Ваша процедура завершится после MsgBox. Но что вы можете сделать, так это двигаться PetFile.Close() в раздел «Наконец» в блоке Try-Catch. Но если вы пытаетесь закрыть файл, который даже не открыт, это вызовет исключение внутри исключения. Лучшее решение — не возиться с этим и использовать диспетчер контекста.

Обратите внимание, что каждая строка в файле должна содержать как минимум 4 поля, разделенных запятыми, иначе код выйдет из строя. Поэтому рекомендуется проверять для каждой строки, что fields.Count = 4 и пропускать строки, не соответствующие этому критерию.

Здесь я заполняю только один список, надеюсь, вы легко разберетесь с остальным.

Imports System.IO

Public Class Form1

    Public Class PetsRecord
        Private m_CustomerName As String
        Private m_CustomerAddress As String
        Private m_PetType As String
        Private m_Vaccinated As String

        Public Property CustomerName() As String
            Get
                Return Me.m_CustomerName
            End Get
            Set(ByVal value As String)
                Me.m_CustomerName = value
            End Set
        End Property

        Public Property CustomerAddress() As String
            Get
                Return Me.m_CustomerAddress
            End Get
            Set(ByVal value As String)
                Me.m_CustomerAddress = value
            End Set
        End Property

        Public Property PetType() As String
            Get
                Return Me.m_PetType
            End Get
            Set(ByVal value As String)
                Me.m_PetType = value
            End Set
        End Property

        Public Property Vaccinated() As String
            Get
                Return Me.m_Vaccinated
            End Get
            Set(ByVal value As String)
                Me.m_Vaccinated = value
            End Set
        End Property
    End Class 'Structure

    Private Sub btnLoad_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLoad.Click
        Dim PetArray As New List(Of PetsRecord)
        Dim bs As New BindingSource()
        Dim PetFile As String = "C:UserstestDocumentspets.txt"

        Using r As StreamReader = New StreamReader(PetFile)
            Dim line As String
            line = r.ReadLine
            Do While (Not line Is Nothing)

                ' split the line into fields
                Dim fields As New List(Of String)(line.Split(","c))
                If fields.Count < 4 Then
                    Console.WriteLine("Skipping line (contains less than 4 fields): " & line)
                Else
                    ' flag this line
                    If fields(3) = "No" Then
                        Dim pet As New PetsRecord
                        pet.CustomerName = fields(0)
                        pet.CustomerAddress = fields(1)
                        pet.PetType = fields(2)
                        pet.Vaccinated = fields(3)
                        PetArray.Add(pet)
                    End If
                End If

                line = r.ReadLine
            Loop
        End Using

        ' bind the listbox to PetArray
        bs.DataSource = PetArray
        Me.lstCustomer.DisplayMember = "CustomerName"
        Me.lstCustomer.DataSource = bs

    End Sub
End Class

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *