Ограничить количество элементов в List (Of String) в VB.NET - PullRequest
0 голосов
/ 04 декабря 2018

Я перебираю файл журнала, используя StreamReader.ReadLine(), в поисках ошибок.Когда я нахожу ошибку, мне нужно посмотреть на предыдущие строки, чтобы увидеть, что произошло.

Но поскольку StreamReader не позволяет мне читать предыдущие строки, мне нужно вести запись предыдущих строк.

Я использовал lineStrings.Add(readfile.ReadLine()), где lineStrings - это List(Of String), а readFile - это StreamReader.

Это прекрасно работает, но некоторые из моих файлов журналов огромны, поэтомусписок становится слишком большим.Сведения об ошибках содержатся только в предыдущих 10 строках любой ошибки, поэтому есть ли способ, чтобы List (Of String) отбрасывал старые строки, когда я добавляю новую, когда список уже состоит из 10 элементов?

Я посмотрел на стеки и очереди, но просто запутался.

Спасибо!

Ответы [ 3 ]

0 голосов
/ 04 декабря 2018

Я бы создал класс StringBuffer, чтобы сохранить только последние n строк.

Public Class StringBuffer
    implements IEnumerable(Of String)

    Private _internalBuffer As LinkedList(Of String)

    Public Sub New(ByVal size As Integer)
        Size = size
        _internalBuffer = New LinkedList(Of String)()
    End Sub

    Public Property Size As Integer

    Public Sub Add(ByVal str As String)
        _internalBuffer.AddFirst(str)
        If _internalBuffer.Count > Size Then _internalBuffer.RemoveLast()
    End Sub

    Public Function GetEnumerator() As IEnumerator(Of String) Implements IEnumerable(Of String).GetEnumerator
        Return _internalBuffer.GetEnumerator()
    End Function

    Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
        Return _internalBuffer.GetEnumerator()
    End Function
End Class

Мы используем LinkedList в качестве внутренней структуры данных для достижения сложности времени O (1) для операции Add(который также может удалить старый элемент).
При повторении вы получите сначала последние записи.

0 голосов
/ 04 декабря 2018

Из вашего описания процесса вы можете использовать Список (из строки) или Очередь (из строки) для хранения последних N строк, прочитанных из журналаfile.

A List(of String), вероятно, немного быстрее, чем Queue(Of String), если производительность вызывает сомнения.

Пример с использованием двух классов:
Примечание: при обнаружении ошибки список (lineStrings) будет содержать MaxElements + 1 элементов.Последняя строка содержит ошибку, остальные MaxElements строки содержат описание ошибки или что-то еще.

Dim MaxElements As Integer = 10
Dim lineStrings As List(Of String) = new List(of String)

'(...)
'Open the file stream using a StreamReader
lineStrings.Add(readfile.ReadLine())
If lineStrings.Last().Contains([Error]) Then
    'Process the error using the lineStrings items
    'Clear the List if the content is not required anymore
    lineStrings.Clear()
End If
If lineStrings.Count > MaxElements Then lineStrings.RemoveAt(0)

Вы можете сделать то же самое с Queue(Of String):

Dim lineStrings As Queue(Of String) = new Queue(of String)(MaxElements)

lineStrings.Enqueue(readfile.ReadLine())
If lineStrings.Last().Contains([Error]) Then
    'Process the error using the lineStrings items
    'Clear the Queue if needed/preferable
    lineStrings.Clear()
End If
If lineStrings.Count > MaxElements Then lineStrings.Dequeue()

Тест скорости, добавление элементов 100,000 и 1,000,000, проверка на ошибки и удаление 10-го элемента из списка, без обработки (скомпилировано как выпуск с использованием файла .exe):

100,000 elements (average):
List(Of String):  21 ms
Queue(Of String): 29 ms

1,000,000 elements (average):
List(Of String):  206 ms
Queue(Of String): 298 ms
0 голосов
/ 04 декабря 2018

Что-то в следующих строках (псевдокод, набранный вручную, но вы должны быть в состоянии перевести):

Dim SB As New StringBuilder
Dim LineCount as Integer = 0

Do While Stream.End
  Dim CurLine = ReadNextLineFromYourStream()
  SB.Append(CurLine)
  LineCount += 1
  If LineCount > 10 Then RemoveFirstLineFromSB
  If ErrorFound Then YouHaveYourLast10LinesIn(SB.ToString())
Loop

Удаление первой строки из StringBuilder так же просто, как SB.Remove(0, SB.IndexOf(vbCrLf)) или любой другой строки-терминатор, который вы используете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...