【问题标题】:How to search multiple text files in a directory for a string of text at once如何一次在目录中的多个文本文件中搜索一串文本
【发布时间】:2020-09-09 18:32:00
【问题描述】:

我有一个列表框,里面有一定数量的项目。
对于 ListBox 中的每个项目,文件目录中都存在一个相应的文本文件。

我需要搜索每个文本文件(基于 ListBox 中的内容)以查找人名。每个文本文件可能包含名称,也可能不包含。
然后我想返回哪个文本文件包含名称。

我已尝试将其作为搜索文本文件的一种方式:它有效,但我不确定如何根据 ListBox 中的内容重复此操作。

Dim sFileContents As String = String.Empty
If (System.IO.File.Exists((Application.StartupPath) & "\Project_Green.txt")) Then
    sFileContents = (System.IO.File.ReadAllText((Application.StartupPath) & "\Project_Green.txt"))
End If
If sFileContents.Contains(TextBox4.Text) Then
    MessageBox.Show("yup")
Else
    MessageBox.Show("nope")
End If

另外,如果可以忽略大小写,那就太好了。

【问题讨论】:

  • 我能问一下为什么数据在文本文件中吗?使用数据库似乎更有意义,但这取决于文本文件到底是什么。

标签: vb.net winforms file search


【解决方案1】:

如果您在一个目录中有一堆文件,并且在 ListBox 中有它们的名称,并且您想搜索它们的内容以查找某些内容。

一个班轮查询:

Imports System.IO
'...

Sub TheCaller()
    Dim dir = My.Application.Info.DirectoryPath
    Dim ext = ".txt" ' If the extensions are trimmed in the list.
    Dim find = TextBox4.Text
    Dim files = Directory.EnumerateFiles(dir).Where(Function(x) ListBox1.Items.Cast(Of String).
        Any(Function(y) String.Concat(y, ext).
        Equals(Path.GetFileName(x),
        StringComparison.InvariantCultureIgnoreCase) AndAlso File.ReadLines(x).
        Any(Function(z) z.IndexOf(find, StringComparison.InvariantCultureIgnoreCase) >= 0))).ToList

    ListBox2.Items.Clear()
    ListBox2.Items.AddRange(files.Select(Function(x) Path.GetFileNameWithoutExtension(x)).ToArray)
End Sub

或者,如果您更喜欢 For Each 循环:

Sub Caller()
    Dim dir = My.Application.Info.DirectoryPath
    Dim find = TextBox4.Text
    Dim files As New List(Of String)

    For Each f As String In ListBox1.Items.Cast(Of String).
        Select(Function(x) Path.Combine(dir, $"{x}.txt"))

        If File.Exists(f) AndAlso
        File.ReadLines(f).Any(Function(x) x.IndexOf(find,
                                StringComparison.InvariantCultureIgnoreCase) <> -1) Then
            files.Add(f)
        End If
    Next

    ListBox2.Items.Clear()
    ListBox2.Items.AddRange(files.Select(Function(x) Path.GetFileNameWithoutExtension(x)).ToArray)
End Sub

无论哪种方式,files 列表都包含匹配项(如果有)。

【讨论】:

  • 我如何将匹配项转储到另一个列表框中?此外,这是否假定其用于搜索的列表框包含文件扩展名 (.txt)?
  • @FarnkD 将files 分配给DataSource 属性,例如:ListBox2.DataSource = files,或者将它们添加到Items 集合中:ListBox2.Items.AddRange(files.ToArray)
  • @FarnkD 如果您只想列出名称而不是全名/路径:ListBox2.Items.AddRange(files.Select(Function(x) Path.GetFileName(x)).ToArray)... 如果您的列表很大,请查看其他答案。
  • 谢谢!效果很好!由此产生的一个问题是,有没有办法将部分文本从标签复制到另一个标签?示例第一个标签是 John.Moore 但我想要的第二个标签是 John
  • @FarnkD Label2.Text = Label1.Text.Split("."c).First
【解决方案2】:

加上一个伪并行异步方法,用于非常繁重的名称搜索。
Async Function SearchNameInTextFiles 返回一个命名元组:

(FileName As String, Index As Integer)

其中 FileName 是解析的文件,Index 是找到指定名称 (theName) 的第一次出现的位置。
如果没有找到匹配的子字符串,则索引值设置为-1

caseSensitive 参数允许指定匹配是否应该区分大小写。

您可以从 Button.Click 异步处理程序(或类似处理程序)开始搜索,如下所示。

Imports System.IO
Imports System.Threading.Tasks

Private Async Sub btnSearchFiles_Click(sender As Object, e As EventArgs) Handles btnSearchFiles.Click
    Dim filesPath = [Your files path]
    Dim theName = textBox4.Text ' $" {textBox4.Text} " to match a whole word
    Dim ext As String = ".txt"  ' Or String.Empty, if extension is already included

    Dim tasks = ListBox1.Items.OfType(Of String).
        Select(Function(f) SearchNameInTextFiles(Path.Combine(filesPath, f & ext), theName, False)).ToList()
    Await Task.WhenAll(tasks)

    Dim results = tasks.Where(Function(t) t.Result.Index >= 0).Select(Function(t) t.Result).ToList()
    results.ForEach(Sub(r) Console.WriteLine($"File: {r.FileName}, Position: {r.Index}"))
End Sub

Private Async Function SearchNameInTextFiles(filePath As String, nameToSearch As String, caseSensitive As Boolean) As Task(Of (FileName As String, Index As Integer))
    If Not File.Exists(filePath) then Return (filePath, -1)
    Using reader As StreamReader = New StreamReader(filePath)
        Dim line As String = String.Empty
        Dim linesLength As Integer = 0
        Dim comparison = If(caseSensitive, StringComparison.CurrentCulture,
                            StringComparison.CurrentCultureIgnoreCase)

        While Not reader.EndOfStream
            line = Await reader.ReadLineAsync()
            Dim position As Integer = line.IndexOf(nameToSearch, comparison)
            If position > 0 Then Return (filePath, linesLength + position)
            linesLength += line.Length
        End While
        Return (filePath, -1)
    End Using
End Function

【讨论】:

    【解决方案3】:

    您可以根据自己的目的执行以下简单步骤:

    1. 首先获取应用启动目录下的所有文本文件。
    2. 然后遍历 ListBox 中的所有名称,并为每个名称在所有文本文件中搜索以找到包含该名称的文件。

    为了使进程不区分大小写,我们首先将名称和文本文件的内容转换为“小写”,然后进行比较。完整代码如下:

        Private Sub findTextFile()
    
            '1- Get all text files in the directory
            Dim myDirInfo As New IO.DirectoryInfo(Application.StartupPath)
            Dim allTextFiles As IO.FileInfo() = myDirInfo.GetFiles("*.txt")
    
            '2- Iterate over all names in the ListBox
            For Each name As String In ListBox1.Items
    
                'Open text files one-by-one and find the first text file that contains this name
                Dim found As Boolean = False 'Changes to true once the name is found in a text file
                Dim containingFile As String = ""
                For Each file As IO.FileInfo In allTextFiles
                    If System.IO.File.ReadAllText(file.FullName).ToLower.Contains(name.ToLower) Then 'compares case-insensitive
                        found = True
                        containingFile = file.FullName
                        Exit For
                    End If
                Next
    
                'Found?
                If found Then
                    MsgBox("The name '" + name + "' found in:" + vbNewLine + containingFile)
                Else
                    MsgBox("The name '" + name + "' does not exist in any text file.")
                End If
            Next
        End Sub
    

    【讨论】:

      猜你喜欢
      • 2018-06-19
      • 2021-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-20
      • 2016-11-29
      相关资源
      最近更新 更多