我正在使用StreamReader.ReadLine()
循环浏览日志文件以查找错误。当我发现错误时,我需要查看前面的代码以查看发生了什么。
但是由于StreamReader不允许我阅读前几行,因此我需要保留前几行的记录。
我一直在使用lineStrings.Add(readfile.ReadLine())
,其中lineStrings
是List(Of String)
,而readFile
是StreamReader
。
这很好用,但是我的一些日志文件很大,因此列表太大了。错误详细信息仅出现在任何错误的前10行中,因此当列表已包含10个元素时,当我添加新行时,有什么办法让List(Of String)丢弃旧行?
我看过堆栈和队列,但只是让自己感到困惑。
谢谢!
答案 0 :(得分:1)
以下几行内容(手工输入的伪代码,但您应该能够翻译):
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))
或您使用的任何行终止符一样简单。
答案 1 :(得分:1)
我将创建一个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
作为内部数据结构来实现Add操作的O(1)时间复杂度(这也可能会删除旧项)。
迭代后,您将首先获得最新条目。
答案 2 :(得分:1)
根据对过程的描述,可以使用List(Of String)或Queue(Of String)保留从日志文件读取的最后N
行。
如果要考虑性能,那么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