我在一个字符串和一行中有一些长文本(例如有关很多书的信息)。
我想找到只有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
答案 0 :(得分: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
正如您所看到的,它不仅更容易阅读,而且还可以配置。您可以将模式外部存储在资源,配置文件,数据库等中。
如果数据尚未全部加载到字符串中,并且效率是最重要的考虑因素,您可能需要考虑使用流读取器,以便一次只将一小部分数据加载到内存中。这种逻辑会有点复杂,但仍然不会太困难。
以下是一个简单的示例,说明如何通过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
答案 1 :(得分: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
AND,在您的模块顶部,包含行Imports System.Text.RegularExpressions
希望这能指出你正确的方向......
答案 2 :(得分: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