我正在开展一个项目,我在这个项目中搜索一个大型文本文件(大的是相对的,文件大小约为1 Gig)。我正在寻找一个令牌,我想在该令牌后立即获得一个美元价值。例如,
这是令牌9,999,999.99
所以这就是我如何处理这个问题。经过一点分析后,看起来令牌通常接近文件的末尾,所以我想我会从文件的末尾开始搜索。这是我到目前为止的代码(vb.net):
Dim sToken As String = "This is a token"
Dim sr As New StreamReader(sFileName_IN)
Dim FileSize As Long = GetFileSize(sFileName_IN)
Dim BlockSize As Integer = CInt(FileSize / 1000)
Dim buffer(BlockSize) As Char
Dim Position As Long = -BlockSize
Dim sBuffer As String
Dim CurrentBlock As Integer = 0
Dim Value As Double
Dim i As Integer
Dim found As Boolean = False
While Not found And CurrentBlock < 1000
CurrentBlock += 1
Position = -CurrentBlock * BlockSize
sr.BaseStream.Seek(Position, SeekOrigin.End)
i = sr.ReadBlock(buffer, 0, BlockSize)
sBuffer = New String(buffer)
found = SearchBuffer(sBuffer, sToken, Value)
End While
GetFileSize是一个返回文件大小的函数。 SearchBuffer是一个搜索字符串以获取令牌的函数。我不熟悉正则表达式,但会针对该函数进行探索。
基本上我读了一小段文件搜索它,如果我发现它没有加载另一个块等等......
我是在正确的轨道还是有更好的方法?
答案 0 :(得分:2)
我认为你在分块文件时有正确的想法。但是,您可能希望在换行符中读取块而不是一组字节数。在您当前的实现中,如果令牌位于1000字节边界上,它可能会被切成两半,从而阻止您找到它。同样的事情也可能导致数据被切断。
答案 1 :(得分:1)
等你们......
如果令牌在两个块之间断开怎么办?你考虑过这个吗?
答案 2 :(得分:0)
如果你要使用块,那么使用长度为512字节的块,并在512字节对齐上寻找是明智的,因为这将更有效地访问磁盘(最终将是512字节块。
可能还有其他粒度甚至更好,但512将是一个良好的开端。
答案 3 :(得分:0)
如果你想做一些更复杂但可能更快的事情,那么你可以看看异步读取块,这样你就可以在下一个加载时搜索一个块。
这样你就可以在数据进入内存的同时进行搜索。
我必须说,除非您的搜索非常昂贵,否则磁盘读取时间可能完全占据主导地位,因此复杂的重叠将不值得额外的复杂性。
答案 4 :(得分:0)
您总是可以使用FileStream搜索文件(或继续按照自己的方式选择)。如果您决定使用FileStream方法,那么您想要做的是这样的:
Dim stream As New FileStream("something.txt")
Dim findBytes As [Byte]() = BitConverter.GetBytes("whatever")
Dim f As Integer = 0
' remaining = Length - Position
While stream.Length - stream.Position > 0
If stream.ReadByte() = findBytes(f) Then
If ++f >= findBytes.Length Then
Console.WriteLine(stream.Position)
Exit While
End If
Else
f = 0
End If
End While
请注意我使用了c#到vb转换器因为我不喜欢vb。
基本思想适用于只搜索块的字符串。如果你想在块中添加读数,这很简单。
答案 5 :(得分:0)
“如果令牌在两个块之间被破坏怎么办?你考虑过这个吗?”
最近才做到这一点。在覆盖CurrentBlock之前,我将CurrentBlock保存到PreviousBlock中,然后将两个Block结合起来,检查找到您正在寻找的搜索词是否没有快乐!效果很好。除非搜索项大于块的长度,否则搜索项无法转义。