【问题标题】:Advanced text search and importing specific strings to VB from file高级文本搜索和将特定字符串从文件导入 VB
【发布时间】:2013-02-26 11:48:52
【问题描述】:

首先我会说这是我在 VBForums 上的第一篇文章,我已经潜伏了一段时间。我对VB相当陌生,只是为了完成我的论文而学习它。所以请原谅我的无知。

我想做的是从另一个程序生成的日志文件中读取数据。我需要将该文件中的特定行带入 VB 以用于其他算法。此日志文件将不断更新,因此如果可能,需要实时读取。

如果重要的话,日志文件是从与另一个软件通信的 USB 设备生成的。

这是一个示例日志:

`
08:57:00.932    COM12
08:57:00.935    COM11
08:57:00.935    COM10
08:57:00.936    COM9
08:57:00.936    COM8
08:57:00.937    COM7
08:57:00.938    COM6
08:57:00.939    COM5
08:57:00.939    COM4
08:57:00.998    --> 0108000304FF0000
08:57:01.007    <-- 0108000304FF0000

TRF7970A EVM 


08:57:01.014    **** COM Port found! ****
08:57:05.009    --> 010A0003041001210000
08:57:05.009    COM4
08:57:05.173    <-- 010A0003041001210000

Register write request.


08:57:05.173    --> 010C00030410002101020000
08:57:05.280    <-- 010C00030410002101020000

Register write request.


08:57:05.280    --> 010B000304140601000000
08:57:05.715    <-- 010B000304140601000000

ISO 15693 Inventory request.

[,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40]D
08:57:05.716    --> 010A0003041001210000
08:57:05.822    <-- 010A0003041001210000

Register write request.


08:57:05.822    --> 010C00030410002101020000
08:57:05.929    <-- 010C00030410002101020000

Register write request.


08:57:05.929    --> 010B000304140601000000
08:57:06.364    <-- 010B000304140601000000

ISO 15693 Inventory request.

[,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40]D
08:57:06.365    --> 010A0003041001210000
08:57:06.470    <-- 010A0003041001210000

Register write request.


08:57:06.470    --> 010C00030410002101020000
08:57:06.576    <-- 010C00030410002101020000

Register write request.


08:57:06.576    --> 010B000304140601000000
08:57:07.011    <-- 010B000304140601000000

ISO 15693 Inventory request.

[,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40]D
08:57:07.012    --> 010A0003041001210000
08:57:07.117    <-- 010A0003041001210000

Register write request.


08:57:07.117    --> 010C00030410002101020000
08:57:07.223    <-- 010C00030410002101020000

Register write request.


08:57:07.223    --> 010B000304140601000000
08:57:07.658    <-- 010B000304140601000000

ISO 15693 Inventory request.

[,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40]D
08:57:07.659    --> 010A0003041001210000
08:57:07.764    <-- 010A0003041001210000

Register write request.


08:57:07.764    --> 010C00030410002101020000
08:57:07.870    <-- 010C00030410002101020000

Register write request.


08:57:07.870    --> 010B000304140601000000
08:57:08.305    <-- 010B000304140601000000

ISO 15693 Inventory request.

[,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40]D
08:57:08.306    --> 010A0003041001210000
08:57:08.411    <-- 010A0003041001210000

Register write request.


08:57:08.411    --> 010C00030410002101020000
08:57:08.517    <-- 010C00030410002101020000

Register write request.


08:57:08.517    --> 010B000304140601000000
08:57:08.952    <-- 010B000304140601000000

ISO 15693 Inventory request.

[,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40]D
08:57:08.952    --> 010A0003041001210000
08:57:09.058    <-- 010A0003041001210000

Register write request.


08:57:09.058    --> 010C00030410002101020000
08:57:09.164    <-- 010C00030410002101020000

Register write request.


08:57:09.164    --> 010B000304140601000000
08:57:09.585    <-- 010B000304140601000000

ISO 15693 Inventory request.

[,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40]

[AD87851A000007E0,7F]

[,40][,40]D
08:57:09.586    --> 010A0003041001210000
08:57:09.692    <-- 010A0003041001210000

Register write request.


08:57:09.692    --> 010C00030410002101020000
08:57:09.798    <-- 010C00030410002101020000

Register write request.


08:57:09.798    --> 010B000304140601000000
08:57:10.233    <-- 010B000304140601000000

ISO 15693 Inventory request.

[,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40][,40]D
08:57:10.234    --> 010A0003041001210000
08:57:10.340    <-- 010A0003041001210000

Register write request.


08:57:10.340    --> 010C00030410002101020000
08:57:10.446    <-- 010C00030410002101020000

Register write request.

`

我需要能够得到这条线: [AD87851A000007E0,7F]

只需“AD87851A000007E0”,然后就可以在 VB 中使用该字符串。这是一个会改变的十六进制代码。

我已经能够从日志文件中读取,但没有产生有效的输出。

这是我一直在尝试使用的代码:

Function ReadData(ByRef keyword As String) As IEnumerable(Of String)
    Dim result = New List(Of String)
    Using reader = New StreamReader("C:\rfid-reader.log")
        Dim line As String = reader.ReadLine()
        Dim take = False
        Do While line IsNot Nothing
            If line.StartsWith("[") Then
                take = False
            End If
            If String.Equals("[" + keyword + ",", line) Then
                take = True
            End If
            If take And Not String.IsNullOrEmpty(line) And Not line.StartsWith("'") Then
                result.Add(line)
            End If
            line = reader.ReadLine()
    Label1.Text = line
        Loop
    End Using
    Return result
End Function

老实说,我不确定代码是否不起作用,或者我只是在将字符串从函数中取出时做错了什么?该函数会按原样打印到 Label1.Text 吗?

我也试过这样调用函数:

Dim items = ReadData("AD87851A000007E0")

Label1.Text = Convert.ToString(items)

这会导致 Label1.Text 变为“System.Collections.Generic.List`1[System.String]”


编辑 1

Imports System.IO

公开课表1

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    Dim items = ReadData("AD87851A000007E0")

    Label1.Text = String.Join(Environment.NewLine, items)


End Sub

Function ReadData(ByRef keyword As String) As IEnumerable(Of String)
    Dim result = New List(Of String)
    Using reader = New StreamReader("C:\rfid-reader.log")
        Dim line As String = reader.ReadLine()
        Dim take = False
        Do While line IsNot Nothing

            take = False ' resetting take = false to avoide printing all lines

            If line.StartsWith("[" + keyword + ",") Then
                take = True
            End If

            If take And Not String.IsNullOrEmpty(line) And Not line.StartsWith("'") Then
                result.Add(line)
            End If
            line = reader.ReadLine()
        Loop
    End Using
    Return result
End Function

结束类

编辑 2______________ em>_________________________________

迄今为止的新代码:

Imports System.IO

公开课表1

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    Dim items = ReadData("AD87851A000007E0")  ' Calling the specific hex code from the function. Advancement needed to get ALL hex codes.

    '   Dim items1 As String = Convert.ToString(items)
    '   Dim items2 As String = ""


    '   Dim k As Long
    '   k = InStrRev(items, ",")
    '   If k > 0 Then items2 = Left$(items, k)

    Label1.Text = String.Join(Environment.NewLine, items)  'Printing function result to Label1


End Sub


'Function to search log file for a specific hex code. Removes not needed portions of the string. Advancements needed: 
'Find ALL hex codes
'Ignore repeats until a reset is set true
'Store each hex code found in it's own variable for use in algorithms


Function ReadData(ByRef keyword As String) As IEnumerable(Of String)
    Dim result = New List(Of String)
    Using reader = New StreamReader("C:\rfid-reader.log")
        Dim line As String = reader.ReadLine()
        Dim take = False

        Do While line IsNot Nothing
            take = False ' resetting take = false to avoide printing all lines

            If line.StartsWith("[" + keyword + ",") Then
                take = True
            End If


            If take And Not String.IsNullOrEmpty(line) And Not line.StartsWith("'") Then
                line = line.Remove(0, 1) 'removing the extra parts of the line
                line = line.Remove(16, 4)
                result.Add(line) 'adding the valid result

            End If
            line = reader.ReadLine()
        Loop
    End Using
    Return result
End Function

结束类


编辑 3

Imports System.IO

公开课表1

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    Dim items = ReadData("[")  ' Calling the specific hex code from the function. Advancement needed to get ALL hex codes.

    Label1.Text = String.Join(Environment.NewLine, items)  'Printing function result to Label1


End Sub


'Function to search log file for a specific hex code. Removes not needed portions of the string. Advancements needed: 
'Find ALL hex codes
'Ignore repeats until a reset is set true
'Store each hex code found in it's own variable for use in algorithms


Function ReadData(ByRef keyword As String) As IEnumerable(Of String)
    Dim result = New List(Of String)
    Using reader = New StreamReader("C:\rfid-reader.log")
        Dim line As String = reader.ReadLine()
        Dim line1 As String = "COOKIES"
        Dim line2 As String = "COOKIES1"
        Dim line3 As String = "COOKIES2"
        Dim line4 As String = "COOKIES3"
        Dim line5 As String = "COOKIES4"
        Dim line6 As String = "COOKIES5"
        Dim line7 As String = "COOKIES6"
        Dim line8 As String = "COOKIES7"
        Dim line1found = False
        Dim line2found = False
        Dim line3found = False
        Dim line4found = False
        Dim line5found = False
        Dim line6found = False
        Dim line7found = False
        Dim line8found = False
        Dim take = False

        Do While line IsNot Nothing

            take = False ' resetting take = false to avoide printing all lines

            If line.StartsWith(keyword) And Not line.StartsWith("[,4") And Not line.StartsWith("[z,") Then
                take = True
            End If

            If line.Contains(line1) Or line.Contains(line2) Or line.Contains(line3) Or line.Contains(line4) Or line.Contains(line5) Or line.Contains(line6) Or line.Contains(line7) Or line.Contains(line8) Then  'attempting to ignore duplicates
                take = False
            End If

            If take And Not String.IsNullOrEmpty(line) And Not line.StartsWith("'") Then
                line = line.Remove(0, 1) 'removing the extra parts of the line
                line = line.Remove(16, 4)
                result.Add(line) 'adding the valid result

                If line1 <> line And Not line1found Then  'assining results to variables for duplicate elimiation
                    line1 = line
                    line1found = True

                ElseIf line2 <> line And line1 <> line And Not line2found Then
                    line2 = line
                    line2found = True

                ElseIf line <> line3 And line <> line2 And line1 <> line And Not line3found Then
                    line3 = line
                    line3found = True

                ElseIf line <> line4 And line <> line3 And line <> line2 And line <> line1 And Not line4found Then
                    line4 = line
                    line4found = True

                ElseIf line <> line5 And line <> line4 And line <> line3 And line <> line2 And line <> line1 And Not line5found Then
                    line5 = line
                    line5found = True

                ElseIf line6 <> line And line5 <> line And line4 <> line And line3 <> line And line2 <> line And line1 <> line And Not line6found Then
                    line6 = line
                    line6found = True

                ElseIf line7 <> line And line6 <> line And line5 <> line And line4 <> line And line3 <> line And line2 <> line And line1 <> line And Not line7found Then
                    line7 = line
                    line7found = True

                ElseIf line8 <> line And line7 <> line And line6 <> line And line5 <> line And line4 <> line And line3 <> line And line2 <> line And line1 <> line And Not line8found Then
                    line8 = line
                    line8found = True

                End If
            End If
            line = reader.ReadLine()
        Loop
    End Using
    Return result
End Function

结束类

【问题讨论】:

  • 有一个主要的事情让我对你的规格感到困惑。您似乎正在此日志文件中搜索给定的字符串。只有一根弦,对吧?您传递给函数的这个“关键字”。但是您还说您需要寻找多个唯一的十六进制代码。我不明白这两个怎么可能都是真的。另外,如果您正在寻找这个单个字符串,为什么要返回一个字符串集合?在我看来,存在一个基本的算法级误解,您需要(首先)获得帮助,而不仅仅是一些 VB 语法。
  • 阅读下面的 clweeks。那是代码的早期阶段,只是让它与一个一起工作。这个想法是找到不止一个。我现在已经完成了。

标签: vb.net file search text


【解决方案1】:

您的代码存在几个问题。第一个问题是您使用的是String.Equals 而不是line.StartsWith

If String.Equals("[" + keyword + ",", line) Then
    take = True
End If

您会注意到,在上面的代码中,只有当整行与字符串“[AD87851A000007E0”完全匹配时,它才会设置take = True。但是您要查找的行不等于该字符串-它仅以该字符串开头。因此,您应该将该代码更改为:

If line.StartsWith("[" + keyword + ",") Then
    take = True
End If

接下来,在循环读取每一行之后,您将在循环内设置Label1.Text = line,无论该行是否匹配。您正在做的事情会起作用,但可能不会以您想要的方式进行。按照您现在的方式,它会用读取的每一行覆盖标签的整个文本内容。正如我所说,它对每一行都这样做,而不仅仅是匹配的行。由于您在循环中忙碌,因此在您完成之前屏幕不会真正刷新,所以最后它只会显示文件中的最后一行。

如果你想让它显示所有匹配的行,你需要将它移动到If take...块内,你需要将这些行连接在一起,像这样:

If take And Not String.IsNullOrEmpty(line) And Not line.StartsWith("'") Then
    result.Add(line)
    Label1.Text = Label1.Text & Environment.NewLine & line
End If

但是,这仍然不是一个很好的方法。将 UI 代码与您的业务逻辑混合绝不是一个好主意,因此您在致电 ReadData 后设置标签的直觉是正确的主意。但是,您不能使用Convert.ToString 来显示列表的内容。如您所见,这只会显示数据类型的名称。为此,您需要将列表中的字符串连接成一个字符串,如下所示:

Label1.Text = String.Join(Environment.NewLine, items)

我使用Environment.NewLine 作为分隔符,但你可以使用任何你想要的分隔符。例如,如果您想将它们全部显示在一行上,您可以使用", " 作为分隔符。

【讨论】:

  • 嗨史蒂文,感谢您的回复!我现在有这部分工作,请在 EDIT 1 中查看我的代码。
  • 现在我需要扩展它。我现在正在编写代码,但任何见解都会很有帮助!正如我在第一篇文章中所说,我正在寻找的十六进制代码会发生变化——所以我需要能够在不查找确切代码的情况下找到它们。一旦我找到一个代码,我需要一个循环来防止它被第二次找到,直到发生重置。我需要能够找到多个代码(一次最多 6 个)并将每个代码存储在自己的变量中。
  • 为了帮助解释我的目标,我将提供更多关于我想要实现的目标的信息:我有一个通过 USB 工作的扫描仪和另一个制作日志文件的软件。它扫描唯一标签并记录每个标签的 ID 号。我需要能够扫描多个标签,然后使用其他算法中的 ID 来确定每个标签代表什么。再次感谢您的帮助,这个级别的 VB 对我来说是新的!
  • 据我了解,您有 ReadData 方法返回十六进制代码列表,其中列表中的每个项目都是一个十六进制代码。因此,您所要做的就是获取它返回的列表并遍历其中的项目,例如:For Each hexCode As String In items。然后,在循环内部,只需通过 hexCode 迭代器变量处理当前项。
  • 我同意。当您有一个字符串列表(或任何集合)(您的十六进制代码)时,您已经将每个字符串都包含在它自己的字符串中。
【解决方案2】:

我迟到了,但这是对您的 Edit 3 的修改,以简化几件事并创建一个框架,允许您扩展验证线路的方式:

Function readData() As List(Of String)
    readData = New List(Of String)
    Using reader As New StreamReader("C:\rfid-reader.log")
        While Not reader.EndOfStream
            For Each line In reader.ReadToEnd.Split(ControlChars.CrLf)
                If validLine(line) AndAlso Not readData.Contains(line.Split(",")(0).Substring(1)) Then readData.Add(line.Split(",")(0).Substring(1))
            Next
        End While
    End Using
End Function

Private Function validLine(line As String) As Boolean
    validLine = True
    'insert criteria to validate the line's format (you could also look at regex)
    If Not line.Trim.Length > 0 Then
        validLine = False
        Exit Function
    End If
    If Not line.Trim.StartsWith("[") AndAlso line.Trim.EndsWith("]") Then
        validLine = False
        Exit Function
    End If
    If Not line.Split(",").Length = 2 Then
        validLine = False
        Exit Function
    End If
    If Not line.Split(",")(0).Substring(1).Length > 1 Then
        validLine = False
        Exit Function
    End If
    If Not isHex(line.Split(",")(0).Substring(1)) Then
        validLine = False
        Exit Function
    End If
    '...
End Function

Private Function isHex(str As String) As Boolean
    isHex = True
    For i = 0 To str.Length - 1
        If Not {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "A", "B", "C", "D", "E", "F"}.Contains(str.Substring(i, 1)) Then
            isHex = False
            Exit Function
        End If
    Next
End Function

【讨论】:

  • 感谢 clweeks 的输入。但是不会有进一步的字符串扩展。正如我在第一篇文章中所说 - 我对 VB 不是很先进。我故意保持代码简单。其他人也必须能够解释它。我确实同意这更加精简 - 但在此阶段不需要。再次感谢您的输入。对上一个答案的 cmets 的任何输入都会有所帮助。
猜你喜欢
  • 1970-01-01
  • 2014-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-28
  • 1970-01-01
  • 2014-08-04
相关资源
最近更新 更多