Лучший способ поиска большого файла для данных в .net - PullRequest
1 голос
/ 30 октября 2008

Я работаю над проектом, в котором я ищу в большом текстовом файле (большой - относительный, размер файла около 1 Гб). Я ищу токен и хочу получить долларовую стоимость сразу после этого токена. Например,

это токен 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 ]

2 голосов
/ 30 октября 2008

Я думаю, у вас есть правильная идея разбить файл на части. Тем не менее, вы можете захотеть читать фрагменты в разрывах строк, а не в установленном количестве байтов. В вашей текущей реализации, если токен находится на границе 1000 байт, он может быть разрезан пополам, что не позволит вам его найти. То же самое может привести к обрезанию данных.

1 голос
/ 03 ноября 2008

Ждем вас, люди ...

Что если токен сломан между двумя кусками? Вы рассматривали это?

0 голосов
/ 14 февраля 2017

«Что, если жетон разбит между двумя кусками? Обдумали ли вы это?»

Сделали это совсем недавно. Я сохранил CurrentBlock в PreviousBlock, перед тем как перезаписать CurrentBlock, а затем женился на двух блоках и проверил, нет ли радости в поиске искомого слова! Работает хорошо. Условие поиска не может быть удалено, если оно не превышает длину блока.

0 голосов
/ 18 марта 2012

Вы всегда можете выполнить поиск в файле, используя 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.

Основная идея относится только к поиску строки в блоке. Это довольно просто, если вы хотите добавить чтение в блоках.

0 голосов
/ 30 октября 2008

Если вы хотите сделать что-то более сложное, но, возможно, более быстрое, то вы можете посмотреть на чтение блоков асинхронно, чтобы вы искали один, пока загружается следующий.

Таким образом, вы можете выполнять поиск одновременно с загрузкой данных в память.

Я должен сказать, что, если ваш поиск не очень дорогой, время чтения с диска, вероятно, будет полностью доминировать, и столь сложное перекрытие не будет стоить дополнительной сложности.

0 голосов
/ 30 октября 2008

Если вы собираетесь использовать чанки, было бы разумно использовать блоки, кратные 512 байтам, и искать выравнивание по 512 байтам, потому что это будет более эффективным при доступе к диску (который в конечном итоге будет в блоках по 512 байт).

Могут быть и другие детали, даже лучше, но 512 будет хорошим началом.

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