繁体   English   中英

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

[英]Best way to search large file for data in .net

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

基本上我读了文件的一小部分进行搜索,如果找不到,则加载另一个文件,依此类推...

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

我认为您对文件进行分块时有正确的主意。 不过,您可能想在换行符处读取块,而不是读取一定数量的字节。 在当前的实现中,如果令牌位于1000字节边界上,则令牌可能会切成两半,从而无法找到它。 同样的事情也可能导致数据被切断。

等你...

如果令牌在两个块之间被破坏怎么办? 你有考虑过吗?

如果要使用块,明智的做法是使用长度为512字节的倍数的块,并尝试以512字节对齐,因为这样做通常会更有效地访问磁盘(最终将存储在磁盘中)。 512字节块)。

可能还有其他更好的粒度,但是512将是一个好的开始。

如果您想做一些更复杂但又可能更快的事情,那么您可以看一下异步读取这些块的方法,以便在下一个正在加载的同时进行搜索。

这样,您就可以在数据进入内存的同时执行搜索。

我不得不说,除非您的搜索非常昂贵,否则磁盘读取时间可能会完全主导这一点,因此,复杂的重叠将不值得额外的复杂性。

“如果令牌在两个块之间被破坏怎么办?您考虑过吗?”

最近才做的。 我先将CurrentBlock保存到PreviousBlock中,然后再覆盖CurrentBlock,然后将这两个Block结合起来,并检查找到所需的搜索词是否愉快! 效果很好。 除非搜索词大于块的长度,否则搜索词不能转义。

您始终可以使用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

只是要注意,我使用了ac#到vb转换器,因为我不喜欢vb。

基本思想适用于仅在块中搜索字符串。 如果要以块为单位添加阅读,这非常简单。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM