Индексируйте файл при загрузке программы.
Создайте Dictionary(Of ULong, Long)
, а когда программа загружается, прочитайте файл.Для каждой строки добавьте запись в словарь, показывающую 13-значное значение в начале каждой строки в качестве ключа ULong и позицию в потоке файла в качестве значения Long.
Затем, когда пользователь вводит ключ, вы можете проверить словарь, который будет почти экземпляром, и затем искать точное местоположение на диске, который вам нужен.
Создание индекса файла при запуске программы может занять несколько минут , но вам когда-либо придется это делать один раз .Прямо сейчас вам нужно либо искать по всему объекту каждый раз, когда пользователь хочет выполнить поиск, либо хранить в памяти несколько сотен мегабайт данных текстового файла.Когда у вас есть индекс, поиск значения в словаре и последующий поиск по нему должны казаться почти мгновенными.
Я только что увидел этот комментарий:
может быть более 1 вхождения из 13-значного числа, поэтому необходимо выполнить поиск по всему файлу.
Исходя из этого, индекс должен быть Dictionary(Of ULong, List(Of Long))
, где при добавлении значения к записи сначала создается экземпляр списка, если он еще не существует, а затем добавляется новое значение в список.
Вот основная попытка, набранная непосредственно в окне ответа без помощи данных тестирования или Visual Studio, которая, вероятно, поэтому все еще содержит несколько ошибок:
Public Class MyFileIndexer
Private initialCapacity As Integer = 1
Private Property FilePath As String
Private Index As Dictionary(Of ULong, List(Of Long))
Public Sub New(filePath As String)
Me.FilePath = filePath
RebuildIndex()
End Sub
Public Sub RebuildIndex()
Index = New Dictionary(Of ULong, List(Of Long))()
Using sr As New StreamReader(FilePath)
Dim Line As String = sr.ReadLine()
Dim position As Long = 0
While Line IsNot Nothing
'Process this line
If Line.Length > 13 Then
Dim key As ULong = ULong.Parse(Line.SubString(0, 13))
Dim item As List(Of Long)
If Not Index.TryGetValue(key, item) Then
item = New List(Of Long)(initialCapacity)
Index.Add(key, item)
End If
item.Add(position)
End If
'Prep for next line
position = sr.BaseStream.Position
Line = sr.ReadLine()
End While
End Using
End Sub
'Expect key to be a 13-character numeric string
Public Function Search(key As String) As List(Of String)
'Will throw an exception if parsing fails. Be prepared for that.
Dim realKey As ULong = ULong.Parse(key)
Return Search(realKey)
End Function
Public Function Search(key As ULong) As List(Of String)
Dim lines As List(Of Long)
If Not Index.TryGetValue(key, lines) Then Return Nothing
Dim result As New List(Of String)()
Using sr As New StreamReader(FilePath)
For Each position As Long In lines
sr.BaseStream.Seek(position, SeekOrigin.Begin)
result.Add(sr.ReadLine())
Next position
End Using
Return Result
End Function
End Class
'Somewhere public, when your application starts up:
Public Index As New MyFileIndexer("G:\USER\FOLDER\tester.txt")
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim lines As List(Of String) = Nothing
Try
lines = Index.Search(TextBox1.Text)
Catch
'Do something here
End Try
If lines IsNot Nothing Then
Using sw As New StreamWriter($"G:\USER\{TextBox1.Text}.txt")
For Each line As String in lines
sw.WriteLine(line)
Next
End Using
End If
End Sub
И для забавы, вот общая версиякласса, который позволяет вам предоставить свою собственную функцию выбора ключа для индексного любого файла, в котором хранится ключ с каждой строкой, что, как я мог видеть, обычно полезно, скажем, для больших наборов данных CSV.
Public Class MyFileIndexer(Of TKey)
Private initialCapacity As Integer = 1
Private Property FilePath As String
Private Index As Dictionary(Of TKey, List(Of Long))
Private GetKey As Func(Of String, TKey)
Public Sub New(filePath As String, Func(Of String, TKey) keySelector)
Me.FilePath = filePath
Me.GetKey = keySelector
RebuildIndex()
End Sub
Public Sub RebuildIndex()
Index = New Dictionary(Of TKey, List(Of Long))()
Using sr As New StreamReader(FilePath)
Dim Line As String = sr.ReadLine()
Dim position As Long = 0
While Line IsNot Nothing
Dim key As TKey = GetKey(Line)
Dim item As List(Of Long)
If Not Index.TryGetValue(key, item) Then
item = New List(Of Long)(initialCapacity)
Index.Add(key, item)
End If
item.Add(position)
'Prep for next line
position = sr.BaseStream.Position
Line = sr.ReadLine()
End While
End Using
End Sub
Public Function Search(key As TKey) As List(Of String)
Dim lines As List(Of Long)
If Not Index.TryGetValue(key, lines) Then Return Nothing
Dim result As New List(Of String)()
Using sr As New StreamReader(FilePath)
For Each position As Long In lines
sr.BaseStream.Seek(position, SeekOrigin.Begin)
result.Add(sr.ReadLine())
Next position
End Using
Return Result
End Function
End Class