在.net中搜索大文件以获取数据的最佳方法

时间:2008-10-30 17:51:03

标签: .net vb.net file parsing

我正在开展一个项目,我在这个项目中搜索一个大型文本文件(大的是相对的,文件大小约为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是一个搜索字符串以获取令牌的函数。我不熟悉正则表达式,但会针对该函数进行探索。

基本上我读了一小段文件搜索它,如果我发现它没有加载另一个块等等......

我是在正确的轨道还是有更好的方法?

6 个答案:

答案 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结合起来,检查找到您正在寻找的搜索词是否没有快乐!效果很好。除非搜索项大于块的长度,否则搜索项无法转义。

相关问题