Textstring zeilenweise auslesen

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von Peter329.

    Textstring zeilenweise auslesen

    Hi,

    Ich habe einen sehr langen Textstring, der einen Text mit Zeilenumbrüchen (CrLf) enthält.

    Diesen Textstring würde ich gern zeilenweise verarbeiten, ähnlich wie man das bei einem File handhabt ... also etwa mit einem StreamReader und den Methoden Peek() und ReadLine().

    Ich weiß aber nicht, wie ich so einem StreamReader eine String Variable (statt eines Files) unterjubeln kann. ich habe auch versucht einen MemoryStream zu verwenden ... aber da finde ich keine passende Vorgehensweise.

    Umgehungen gibt es viele. Ich könnte die Stringvariable mit WriteAllText in einen File schreiben und den File dann lesen ... oder ich könnte die String Variable mit .Split(CrLf) in einen Vektor umwandeln ... aber das sieht mir alles verteufelt umständlich aus.

    Wie mache ich das denn eleganter ?

    LG
    Peter
    Das geht aber m.E. nicht, da .Split() nur EinzelChars nimmt oder eine Gruppe von Chars. Da CrLf aber ein String ist, müsste man Cr und Lf einzeln in einem CharArray angeben, aber dann wird eben auch an alleinigen Crs und Lfs gesplittet. Ohne Regex z.B.:

    VB.NET-Quellcode

    1. Public Module Extensions
    2. <Runtime.CompilerServices.Extension>
    3. Public Function SplitAtNewLine(Text As String) As String()
    4. Dim FinalStringList As New List(Of String)
    5. Dim RemainingText = Text
    6. Do
    7. Dim IndexOfNextNewLine = RemainingText.IndexOf(Environment.NewLine)
    8. If IndexOfNextNewLine = -1 Then
    9. FinalStringList.Add(RemainingText)
    10. Exit Do
    11. ElseIf IndexOfNextNewLine = 0 Then
    12. FinalStringList.Add(String.Empty)
    13. RemainingText = RemainingText.Substring(2)
    14. Else
    15. FinalStringList.Add(RemainingText.Substring(0, IndexOfNextNewLine))
    16. RemainingText = RemainingText.Substring(IndexOfNextNewLine + 2)
    17. End If
    18. Loop
    19. Return FinalStringList.ToArray
    20. End Function
    21. End Module
    mit Regex angeblich: System.Text.RegularExpressions.Regex.Split(str, vbCrLf), zumindest laut stackoverflow
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @Peter329 Oder Du weist einer TextBox den String per .Text zu und liest ihn per .Lines wieder aus.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    VaporiZed schrieb:

    Das geht aber m.E. nicht, da .Split() nur EinzelChars nimmt oder eine Gruppe von Chars.
    Na, da gibts durchaus geeignete Überladungen - zB

    ObjectBrowser schrieb:

    Public Function Split(separator As String(), count As Integer, options As System.StringSplitOptions) As String()
    Member of System.String

    Ehm ... ja :D erfolgreich zuviel gearbeitet. Du hast recht: DerText.Split({Environment.NewLine}, StringSplitOptions.None)
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Dem StringBuilder trau ich das auch zu

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub Sample()
    2. Dim cnt = 1_000_000I
    3. Dim sb = New StringBuilder(cnt)
    4. For i As Int32 = 0 To cnt - 1
    5. sb.Append($"Mein extrem langer string {i}.")
    6. sb.AppendLine()
    7. Next
    8. Dim res = GetSpecialSplit(sb.ToString, Environment.NewLine)
    9. Stop
    10. End Sub
    11. Private Function GetSpecialSplit(s As String, sep As String) As String()
    12. If String.IsNullOrEmpty(s) Then Return Nothing
    13. Dim idx = -1I, idx2 = 0I
    14. Dim res = New StringBuilder(s.Length)
    15. Do
    16. If idx + sep.Length = s.Length Then Exit Do
    17. idx = s.IndexOf(sep, idx + 1)
    18. If idx = -1 Then
    19. res.Append(s.Substring(idx2, s.Length - idx2))
    20. Exit Do
    21. ElseIf idx = 0 Then
    22. idx += sep.Length
    23. Else
    24. res.Append(s.Substring(idx2, idx - idx2))
    25. res.AppendLine()
    26. End If
    27. idx2 = idx
    28. Loop
    29. Return res.ToString.Split(Environment.NewLine.ToCharArray,
    30. StringSplitOptions.RemoveEmptyEntries)
    31. End Function

    Yield

    VB.NET-Quellcode

    1. Private Sub Sample()
    2. Dim cnt = 1_000_000I
    3. Dim sb = New StringBuilder(cnt)
    4. sb.AppendLine()
    5. For i As Int32 = 0 To cnt - 1
    6. sb.Append($"Mein extrem langer string {i}.")
    7. sb.AppendLine()
    8. Next
    9. Dim tmp = New StringBuilder(sb.Length)
    10. For Each s As String In GetSpecialSplitYield(sb.ToString, Environment.NewLine)
    11. tmp.Append(s)
    12. tmp.AppendLine()
    13. Next
    14. Dim res = tmp.ToString.Split(Environment.NewLine.ToCharArray,
    15. StringSplitOptions.RemoveEmptyEntries)
    16. Stop
    17. End Sub
    18. Private Iterator Function GetSpecialSplitYield(s As String, sep As String) _
    19. As IEnumerable(Of String)
    20. If String.IsNullOrEmpty(s) Then Exit Function
    21. If String.IsNullOrEmpty(sep) Then Exit Function
    22. If s = sep Then Exit Function
    23. If s.Length <= sep.Length Then Yield s
    24. Dim idx = -1I, idx2 = 0I
    25. Do
    26. If idx + sep.Length = s.Length Then Exit Do
    27. idx = s.IndexOf(sep, idx + 1)
    28. If idx = -1 Then
    29. Yield s.Substring(idx2, s.Length - idx2)
    30. Exit Do
    31. ElseIf idx = 0 Then
    32. idx += sep.Length
    33. Else : Yield s.Substring(idx2, idx - idx2)
    34. End If
    35. idx2 = idx
    36. Loop
    37. End Function

    Stream

    VB.NET-Quellcode

    1. tmp = New StringBuilder(sb.Length)
    2. Dim ms = New MemoryStream()
    3. Dim sw = New StreamWriter(ms)
    4. sw.Write(sb.ToString)
    5. sw.Flush() 'WICHTIG!!!!!
    6. Using ssr = New StreamReader(ms)
    7. ms.Position = 0
    8. Dim line As String
    9. While Not ssr.EndOfStream
    10. line = ssr.ReadLine
    11. If line.Length < 1 Then
    12. Continue While
    13. End If
    14. tmp.Append(line)
    15. tmp.AppendLine()
    16. End While
    17. End Using
    18. 'Zur Kontrolle
    19. Dim res = tmp.ToString.Split(Environment.NewLine.ToCharArray,
    20. StringSplitOptions.RemoveEmptyEntries)


    Freundliche Grüsse

    exc-jdbi

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „exc-jdbi“ ()

    Vielen Dank für die Antworten.

    da bin ich ja erst mal beruhigt, dass es nicht möglich ist, einen String so einfach einem Reader unterzuschieben. Es hätte ja auch sein können, dass ich da (ein ums andere Mal) irgendeine elementare .Net Funktionaliät übersehen hätte.:)

    Ich habe mich jetzt für die Überlagerung der .Split Funktion entschieden. Eine Zeile Code und das Dingens ist erledigt und funktioniert prima.

    LG
    Peter

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Peter329“ ()

    ok ok ... jau, da wäre ich wohl doch besser deinem Ratschlag eingehender nachgegangen. :)

    Denn tatsächlich ist es so, dass diese Lösung für mein Problem die BESSERE Alternative ist !

    Was ich nicht eingestellt hatte: manchmal erhalte ich die Eingabe aus einem Text FILE ... und manchmal aus einem Text STRING. Mit deiner Idee kann ich einen StreamReader oder einen StringReader aufmachen und dann die Eingabe in genau der gleichen Weise verarbeiten. Ich bin begeistert!

    Also DANKE für deinen Hinweis, der mich jetzt doch zu einer noch besseren Lösung geführt hat.

    off topic: Das ist halt der große Vorteil eines Forums. Dass man aus der Vielzahl der Meinungen und Ideen dann oft eine optimale Lösung erhält.

    LG
    Peter

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Peter329“ ()