it-swarm.com.de

Der einfachste Weg, einen String in .NET in Zeilenumbrüche zu teilen?

Ich muss einen String in .NET in Zeilenumbrüche aufteilen und die einzige mir bekannte Möglichkeit, Strings aufzuteilen, ist die Split -Methode. Das erlaubt mir jedoch nicht, mich (leicht) von einer neuen Zeile zu trennen. Was ist also der beste Weg, dies zu tun?

731
RCIX

Um einen String aufzuteilen, müssen Sie die Überladung verwenden, die ein Array von Strings benötigt:

string[] lines = theText.Split(
    new[] { Environment.NewLine },
    StringSplitOptions.None
);

Bearbeiten:
Wenn Sie verschiedene Arten von Zeilenumbrüchen in einem Text verarbeiten möchten, können Sie die Möglichkeit nutzen, mehrere Zeichenfolgen zuzuordnen. Dies wird bei beiden Arten von Zeilenumbrüchen korrekt aufgeteilt und es werden leere Zeilen und Abstände im Text beibehalten:

string[] lines = theText.Split(
    new[] { "\r\n", "\r", "\n" },
    StringSplitOptions.None
);
1288
Guffa

Was ist mit einem StringReader ?

using (System.IO.StringReader reader = new System.IO.StringReader(input)) {
    string line = reader.ReadLine();
}
103
Clément

Du solltest in der Lage sein, deine Saite ziemlich leicht zu teilen, wie folgt:

aString.Split(Environment.NewLine.ToCharArray());
44
nikmd23

Vermeiden Sie die Verwendung von string.Split für eine allgemeine Lösung, da Sie überall, wo Sie die Funktion verwenden, mehr Speicherplatz benötigen - die ursprüngliche Zeichenfolge und die geteilte Kopie, beide im Speicher. Vertrauen Sie mir, dass dies ein echtes Problem sein kann, wenn Sie mit dem Skalieren beginnen. Führen Sie eine 32-Bit-Stapelverarbeitungs-App aus, die 100 MB-Dokumente verarbeitet, und Sie werden acht Threads gleichzeitig überflüssig. Nicht, dass ich schon einmal dort gewesen wäre ...

Verwenden Sie stattdessen einen Iterator wie diesen.

    public static IEnumerable<string> SplitToLines(this string input)
    {
        if (input == null)
        {
            yield break;
        }

        using (System.IO.StringReader reader = new System.IO.StringReader(input))
        {
            string line;
            while( (line = reader.ReadLine()) != null)
            {
                yield return line;
            }
        }
    }

Auf diese Weise können Sie eine speichereffizientere Schleife um Ihre Daten durchführen.

foreach(var line in document.SplitToLines()) 
{
    // one line at a time...
}

Natürlich können Sie dies tun, wenn Sie alles im Speicher haben möchten.

var allTheLines = document.SplitToLines.ToArray();
25
Steve Cooper

Basierend auf Guffas Antwort verwenden Sie in einer Erweiterungsklasse:

public static string[] Lines(this string source) {
    return source.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
}
23
Erwin Mayer

Für eine Zeichenfolgenvariable s:

_s.Split(new string[]{Environment.NewLine},StringSplitOptions.None)
_

Hierbei wird die Definition der Zeilenenden in Ihrer Umgebung verwendet. Unter Windows lauten die Zeilenenden CR-LF (Wagenrücklauf, Zeilenvorschub) oder in C # die Escapezeichen _\r\n_.

Dies ist eine zuverlässige Lösung, denn wenn Sie die Zeilen mit String.Join neu kombinieren, entspricht dies Ihrer ursprünglichen Zeichenfolge:

_var lines = s.Split(new string[]{Environment.NewLine},StringSplitOptions.None);
var reconstituted = String.Join(Environment.NewLine,lines);
Debug.Assert(s==reconstituted);
_

Was Sie nicht tun sollten:

  • Verwenden Sie StringSplitOptions.RemoveEmptyEntries , da dies Markups wie Markdown unterbricht, wenn leere Zeilen syntaktischen Zweck haben.
  • Split on separator _new char[]{Environment.NewLine}_, da unter Windows ein leeres Zeichenfolgenelement für jede neue Zeile erstellt wird.
8
Colonel Panic

Regex ist auch eine Option:

    private string[] SplitStringByLineFeed(string inpString)
    {
        string[] locResult = Regex.Split(inpString, "[\r\n]+");
        return locResult;
    }
7
user1964822

Ich dachte nur, ich würde meine Zwei-Bits hinzufügen, weil die anderen Lösungen zu dieser Frage nicht in die wiederverwendbare Code-Klassifizierung fallen und nicht bequem sind.

Der folgende Codeblock erweitert das Objekt string, sodass es als natürliche Methode beim Arbeiten mit Zeichenfolgen verfügbar ist.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using System.Collections.ObjectModel;

namespace System
{
    public static class StringExtensions
    {
        public static string[] Split(this string s, string delimiter, StringSplitOptions options = StringSplitOptions.None)
        {
            return s.Split(new string[] { delimiter }, options);
        }
    }
}

Sie können nun die Funktion .Split() aus einer beliebigen Zeichenfolge wie folgt verwenden:

string[] result;

// Pass a string, and the delimiter
result = string.Split("My simple string", " ");

// Split an existing string by delimiter only
string foo = "my - string - i - want - split";
result = foo.Split("-");

// You can even pass the split options parameter. When omitted it is
// set to StringSplitOptions.None
result = foo.Split("-", StringSplitOptions.RemoveEmptyEntries);

Übergeben Sie zum Teilen eines Zeilenumbruchs einfach "\n" oder "\r\n" als Begrenzungsparameter.

Kommentar: Es wäre schön, wenn Microsoft diese Überladung implementieren würde.

6
Kraang Prime

Ich benutze derzeit diese Funktion (basierend auf anderen Antworten) in VB.NET:

Private Shared Function SplitLines(text As String) As String()
    Return text.Split({Environment.NewLine, vbCrLf, vbLf}, StringSplitOptions.None)
End Function

Es wird zunächst versucht, die plattformlokale Zeile zu teilen, und dann wird auf jede mögliche Zeile zurückgegriffen.

Ich habe das bisher nur in einer Klasse gebraucht. Wenn sich dies ändert, werde ich dieses Public wahrscheinlich in eine Utility-Klasse verschieben und es möglicherweise sogar zu einer Erweiterungsmethode machen.

So fügen Sie die Zeilen sicher zusammen:

Private Shared Function JoinLines(lines As IEnumerable(Of String)) As String
    Return String.Join(Environment.NewLine, lines)
End Function
4
Rory O'Kane

Nun, eigentlich sollte split tun:

//Constructing string...
StringBuilder sb = new StringBuilder();
sb.AppendLine("first line");
sb.AppendLine("second line");
sb.AppendLine("third line");
string s = sb.ToString();
Console.WriteLine(s);

//Splitting multiline string into separate lines
string[] splitted = s.Split(new string[] {System.Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries);

// Output (separate lines)
for( int i = 0; i < splitted.Count(); i++ )
{
    Console.WriteLine("{0}: {1}", i, splitted[i]);
}
2
MaciekTalaska
string[] lines = text.Split(
  Environment.NewLine.ToCharArray(), 
  StringSplitOptions.RemoveEmptyStrings);

Die Option RemoveEmptyStrings stellt sicher, dass Sie keine leeren Einträge haben, weil\n einem\r folgt

(Bearbeiten, um Kommentare wiederzugeben :) Beachten Sie, dass auch echte Leerzeilen im Text verworfen werden. Dies ist normalerweise das, was ich will, aber es könnte nicht Ihre Anforderung sein.

1
Serge Wautier

Ich wusste nichts über Environment.Newline, aber ich denke, das ist eine sehr gute Lösung.

Mein Versuch wäre gewesen:

        string str = "Test Me\r\nTest Me\nTest Me";
        var splitted = str.Split('\n').Select(s => s.Trim()).ToArray();

Der zusätzliche .Trim entfernt alle\r oder\n, die möglicherweise noch vorhanden sind (z. B. wenn unter Windows eine Zeichenfolge mit os x Zeilenumbrüchen geteilt wird). Wahrscheinlich nicht die schnellste Methode.

BEARBEITEN:

Wie in den Kommentaren richtig angegeben, werden dadurch auch Leerzeichen am Zeilenanfang oder vor dem Zeilenvorschub entfernt. Wenn Sie dieses Leerzeichen beibehalten müssen, verwenden Sie eine der anderen Optionen.

0
Max