Лучший способ искать данные в большом файле в .net

Я работаю над проектом, в котором я ищу фрагмент данных в большом текстовом файле (большой - относительный, размер файла составляет около 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 - это функция, которая будет искать токен в строке. Я не знаком с регулярными выражениями, но изучу их для этой функции.

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

Я на правильном пути или есть лучший способ?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
3 086
6

Ответы 6

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

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

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

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

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

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

Подождите, народ ...

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

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

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

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

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

Другие вопросы по теме