3

我在一个字符串和一行中有一些长文本(例如有关许多书籍的信息)。

我只想找到 ISBN(只有数字 - 每个数字都被字符 ISBN 阻止)。我找到了如何在第一个位置提取这个数字的代码。问题是如何为所有文本创建循环。我可以将它用于这个示例流阅读器吗?谢谢您的回答。

例子:

Sub Main()
    Dim getLiteratura As String = "'Author 1. Name of book 1. ISBN 978-80-251-2025-5.', 'Author 2. Name of Book 2. ISBN 80-01-01346.', 'Author 3. Name of book. ISBN 80-85849-83.'"
    Dim test As Integer = getLiteratura.IndexOf("ISBN")
    Dim getISBN As String = getLiteratura.Substring(test + 5, getLiteratura.IndexOf(".", test + 1) - test - 5)

    Console.Write(getISBN)
    Console.ReadKey()
End Sub
4

3 回答 3

3

由于您可以将开始位置传递给IndexOf方法,因此您可以通过从上次迭代停止的位置开始搜索来循环字符串。例如:

Dim getLiteratura As String = "'Author 1. Name of book 1. ISBN 978-80-251-2025-5.', 'Author 2. Name of Book 2. ISBN 80-01-01346.', 'Author 3. Name of book. ISBN 80-85849-83.'"
Dim isbns As New List(Of String)()
Dim position As Integer = 0
While position <> -1
    position = getLiteratura.IndexOf("ISBN", position)
    If position <> -1 Then
        Dim endPosition As Integer = getLiteratura.IndexOf(".", position + 1)
        If endPosition <> -1 Then
            isbns.Add(getLiteratura.Substring(position + 5, endPosition - position - 5))
        End If
        position = endPosition
    End If
End While

如果数据已经全部加载到字符串中,那将与您可能找到的方法一样有效。但是,该方法的可读性或灵活性不高。如果这些事情不仅仅关注效率,您可能需要考虑使用 RegEx:

For Each i As Match In Regex.Matches(getLiteratura, "ISBN (?<isbn>.*?)\.")
    isbns.Add(i.Groups("isbn").Value)
Next

如您所见,它不仅更易于阅读,而且还可以配置。您可以将模式外部存储在资源、配置文件、数据库等中。

如果数据还没有全部加载到字符串中,并且效率是最重要的问题,您可能需要考虑使用流读取器,以便一次只将一小部分数据加载到内存中。这个逻辑会有点复杂,但仍然不会太难。

这是一个简单的示例,说明如何通过 a 进行操作StreamReader

Dim isbns As New List(Of String)()
Using reader As StreamReader = New StreamReader(stream)
    Dim builder As New StringBuilder()
    Dim isbnRegEx As New Regex("ISBN (?<isbn>.*?)\.")
    While Not reader.EndOfStream
        Dim charValue As Integer = reader.Read()
        If charValue <> -1 Then
            builder.Append(Convert.ToChar(charValue))
            Dim matches As MatchCollection = isbnRegEx.Matches(builder.ToString())
            If matches.Count <> 0 Then
                For Each i As Match In matches
                    isbns.Add(i.Groups("isbn").Value)
                Next
                builder.Clear()
            End If
        End If
    End While
End Using

如您所见,在该示例中,一旦找到匹配项,它就会将其添加到列表中,然后清除builder用作缓冲区的匹配项。这样,一次保存在内存中的数据量永远不会超过一个“记录”的大小。

更新

由于根据您的评论,您无法使其正常工作,因此这是一个完整的工作示例,它输出ISBN 编号,没有任何周围的字符。只需创建一个新的 VB.NET 控制台应用程序并粘贴以下代码:

Imports System.Text.RegularExpressions

Module Module1
    Public Sub Main()
        Dim data As String = "'Author 1. Name of book 1. ISBN 978-80-251-2025-5.', 'Author 2. Name of Book 2. ISBN 80-01-01346.', 'Author 3. Name of book. ISBN 80-85849-83.'"
        For Each i As String In GetIsbns(data)
            Console.WriteLine(i)
        Next
        Console.ReadKey()
    End Sub

    Public Function GetIsbns(data As String) As List(Of String)
        Dim isbns As New List(Of String)()
        For Each i As Match In Regex.Matches(data, "ISBN (?<isbn>.*?)\.")
            isbns.Add(i.Groups("isbn").Value)
        Next
        Return isbns
    End Function
End Module
于 2013-09-04T13:39:33.733 回答
0

在处理大量数据时,我建议使用正则表达式。

尝试这样的事情:

    Dim getLiteratura As String = "'Author 1. Name of book 1. ISBN 978-80-251-2025-5.', 'Author 2. Name of Book 2. ISBN 80-01-01346.', 'Author 3. Name of book. ISBN 80-85849-83.'"
    Dim Pattern As String = "ISBN (.*?)\."
    Dim ReturnedMatches As MatchCollection = Regex.Matches(getLiteratura, Pattern)
    For Each ReturnedMatch As Match In ReturnedMatches
        MsgBox(ReturnedMatch.Groups(1).ToString)
    Next

并且,在您的模块顶部,包括该行Imports System.Text.RegularExpressions

希望这能为您指明正确的方向...

于 2013-09-04T13:44:20.073 回答
0

这是我的解决方案

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim outputtext As New String("")
    Dim test As Integer = 0
    Dim getLiteratura As String = "'Author 1. Name of book 1. ISBN 978-80-251-2025-5.', 'Author 2. Name of Book 2. ISBN 80-01-01346.', 'Author 3. Name of book. ISBN 80-85849-83.'"
    test = getLiteratura.IndexOf("ISBN")
    Dim getISBN As String = ""
    While Not getLiteratura.Substring(test + 5, getLiteratura.IndexOf(".", test + 1) - test - 5).Length = 0
        outputtext = outputtext & getLiteratura.Substring(test + 5, getLiteratura.IndexOf(".", test + 1) - test - 5) & " : "
        If getLiteratura.Substring(test + 1).IndexOf("ISBN") = 0 Then
            Exit While
        Else
            test = test + getLiteratura.Substring(test + 1).IndexOf("ISBN")
        End If
    End While

    Label1.Text = outputtext
End Sub
于 2013-09-04T13:47:03.593 回答