Правильный способ работы с .txt-файлами в объектно-ориентированном программировании

Программа, над которой я работаю, работает с несколькими разными .txt-файлами для хранения своих данных. Скажем так, наш файл выглядит так:

a1; b1; c1; 
a2; b2; c2; 
...

Для работы с таким файлом я сделал класс, допустим он называется CFile. Теперь я написал функцию для получения каждого из векторов a, b и c. Они работают примерно так:

Public Shared Function getAFromFile() As List(Of Double)
        Dim datei As New FileStream(filePathSelectedInForm, FileMode.Open)
        Dim leser As New StreamReader(datei)
        Dim zeile As String
        Dim werte() As String

        Dim a As New List(Of Double)
        Dim b As New List(Of Double)
        Dim c As New List(Of Double)
        While leser.Peek <> -1
            zeile = leser.ReadLine
            werte = zeile.Split(";")
            a.Add(werte(0))
            b.Add(werte(1))
            c.Add(werte(2))
        End While

        leser.Close()
        datei.Close()

        getAFromFile = a
    End Function

Конечно, я хочу что-то вычислить с данными сейчас. Допустим, я хочу умножить каждое значение Double на значение Double другого файла с именем x, а затем добавить еще одно значение с именем r. Поэтому я создаю еще одну функцию в своем классе примерно так:

   Public Shared Function calculateWithA(r as Double) As List(Of Double)
        dim a as List(Of Double) = getAFromFile()
        dim x as List(Of Double) = getXFromFile()
        Dim result As New List(Of Double)
        For i = 0 To a.Count - 1
            result.Add(a.Item(i) * x.Item(i) + r)
        Next
        calculateWithA = result  
   End Function

Допустим, у нас есть представление данных в форме, и оно заполнено нашими векторами a, b и c. Итак, у нас есть 3 столбца и неопределенное количество строк, в зависимости от количества элементов a, b и c из текстового файла. Теперь я добавляю 4-ю строку, в которой хочу хранить рассчитанные значения. Правильный способ - открыть мой файл, получить вектор a, открыть другой файл, получить вектор x, умножить их, добавить r и затем записать его в datagridview.

Теперь представьте, что r — это индекс строки datagridview. Теперь мне нужен цикл от r = 0 до «количества строк-1» и вызова calculateWithA (r). Каждый раз, когда вызывается функция, в ней вызываются две функции getAFromFile() и getXFromFile(). Я предполагаю, что открытие файла происходит довольно медленно, поэтому я думаю, что было бы лучше сделать a и x публичным общим списком (Of Double) и просто получить их один раз, а затем работать с ними в функции calculateWithA. Что-то вроде этого:

 Private Shared a As New List(Of Double)
 Private Shared x As New List(Of Double)

 Public Shared sub getAandX()
            a  = getAFromFile()
            x  = getXFromFile()
            Dim result As New List(Of Double)
            For i = 0 To a.Count - 1
                result.Add(a.Item(i) * x.Item(i) + r)
            Next
 End Sub

 Public Shared Function calculateWithA(r as Double) As List(Of Double)
            Dim result As New List(Of Double)
            For i = 0 To a.Count - 1
                result.Add(a.Item(i) * x.Item(i) + r)
            Next
            calculateWithA = result  
       End Function

В этом случае я могу вызывать calculateWithA(r) несколько раз, в то время как ресурсоемкие функции, работающие с файлом, вызываются только один раз. Но я ДОЛЖЕН вызвать getAandX() перед использованием calculateWithA(r), иначе я получу ошибку или буду работать со старыми значениями a и x. Вот в чем моя проблема: я хочу, чтобы моя программа была как можно более модульной и следовала правилам объектно-ориентированной программы. Но если мне нужно вызвать функцию, чтобы убедиться, что другая функция работает, это противоречит этим правилам, верно? Но если я работаю со своей модульной версией, вызывая каждый файл каждый раз, когда я вызываю функцию, я получаю довольно плохую производительность и долгое время ожидания. Что вы, ребята, говорите? Куда мне идти или есть лучший способ решить эту проблему?

Заранее спасибо!


person Community    schedule 07.01.2015    source источник


Ответы (1)


В этом случае, я думаю, вы должны вызвать getAandX из calculateWithA, чтобы сначала проверить, пусты ли списки или нет. Если они пусты, вызовите getAandX, а затем запустите цикл, чтобы получить результаты. После цикла очистите списки a и x, так как они больше не нужны. Теперь каждый раз, когда вы вызываете calculateWithA, он сначала обновляет данные, а затем обрабатывает их. Таким образом, файловый ввод-вывод произойдет один раз, а ответственность за загрузку данных будет возложена на функцию calculateWithA.

person SV.    schedule 07.01.2015
comment
Но в этом случае я ДОЛЖЕН очистить списки после цикла. Если я забуду об этом, в следующий раз это не сработает. Поэтому мне снова приходится вызывать функцию, чтобы убедиться, что другая функция работает правильно. Просто вместо того, чтобы вызывать функцию перед циклом, я должен вызывать функцию сразу после цикла. Я думаю, что шляпа не объектно-ориентированная. - person ; 07.01.2015