web-dev-qa-db-fra.com

Le moyen le plus simple de scinder une chaîne sur des nouvelles lignes dans .NET?

J'ai besoin de scinder une chaîne en nouvelles lignes dans .NET et la seule façon dont je connaisse cette opération consiste à utiliser la méthode Split . Cependant, cela ne me permettra pas (facilement) de me séparer sur une nouvelle ligne, alors quelle est la meilleure façon de le faire?

731
RCIX

Pour diviser une chaîne, vous devez utiliser la surcharge qui prend un tableau de chaînes:

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

Modifier:
Si vous souhaitez gérer différents types de sauts de ligne dans un texte, vous pouvez utiliser la possibilité de faire correspondre plusieurs chaînes. Cela divisera correctement sur l'un ou l'autre type de saut de ligne et préservera les lignes vides et l'espacement dans le texte:

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

Qu'en est-il de l'utilisation de StringReader ?

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

Vous devriez pouvoir séparer votre chaîne assez facilement, comme ceci:

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

Essayez d'éviter d'utiliser string.Split pour une solution générale, car vous utiliserez plus de mémoire partout où vous utiliserez la fonction - la chaîne d'origine et la copie divisée, les deux en mémoire. Croyez-moi, cela peut être un sacré problème lorsque vous commencez à faire évoluer votre système: exécutez une application de traitement par lots 32 bits traitant des documents de 100 Mo, et vous perdrez huit threads simultanés. Pas que j'y sois allé avant ...

Au lieu de cela, utilisez un itérateur comme celui-ci;

    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;
            }
        }
    }

Cela vous permettra de faire une boucle plus efficace en termes de mémoire autour de vos données;

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

Bien sûr, si vous voulez tout en mémoire, vous pouvez le faire;

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

D'après la réponse de Guffa, dans une classe d'extension, utilisez:

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

Pour une variable chaîne s:

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

Ceci utilise la définition de fin de ligne de votre environnement. Sous Windows, les fins de ligne sont CR-LF (retour chariot, saut de ligne) ou dans les caractères d’échappement de C # _\r\n_.

C'est une solution fiable, car si vous recombinez les lignes avec String.Join , cela équivaut à votre chaîne d'origine:

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

Ce qu'il ne faut pas faire:

  • Utilisez StringSplitOptions.RemoveEmptyEntries , car cela briserait le balisage, tel que Markdown, où les lignes vides ont un objectif syntaxique.
  • Fractionner sur le séparateur _new char[]{Environment.NewLine}_ car, sous Windows, un élément de chaîne vide sera créé pour chaque nouvelle ligne.
8
Colonel Panic

Regex est aussi une option:

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

J'ai juste pensé que j'ajouterais mes deux bits, parce que les autres solutions sur cette question ne relèvent pas de la classification de code réutilisable et ne sont pas pratiques.

Le bloc de code suivant étend l'objet string afin qu'il soit disponible en tant que méthode naturelle lors de l'utilisation de chaînes.

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);
        }
    }
}

Vous pouvez maintenant utiliser la fonction .Split() à partir de n’importe quelle chaîne, comme suit:

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);

Pour séparer un caractère de nouvelle ligne, il suffit de passer "\n" ou "\r\n" en tant que paramètre de délimiteur.

Commentaire: Ce serait bien si Microsoft implémentait cette surcharge.

6
Kraang Prime

J'utilise actuellement cette fonction (basée sur d'autres réponses) dans VB.NET:

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

Il essaie d'abord de se scinder sur la nouvelle ligne locale à la plate-forme, puis revient à chaque nouvelle ligne possible.

Je n'ai eu besoin de ça que dans une classe jusqu'à présent. Si cela change, je vais probablement faire ceci Public et le déplacer dans une classe utilitaire, et peut-être même en faire une méthode d'extension.

Voici comment joindre les lignes de secours, pour faire bonne mesure:

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

En fait, la séparation devrait suffire:

//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);

L'option RemoveEmptyStrings assurera que vous n'avez pas d'entrées vides car\n suit un\r

(Modifiez pour refléter les commentaires :) Notez qu'il supprimera également les lignes vides authentiques dans le texte. C’est généralement ce que je veux, mais ce n’est peut-être pas ce dont vous avez besoin.

1
Serge Wautier

Je ne connaissais pas Environment.Newline, mais je suppose que c'est une très bonne solution.

Mon essai aurait été:

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

Le fichier .Trim supplémentaire supprime tout\r ou\n qui pourrait être encore présent (par exemple, lorsque vous êtes sous Windows mais que vous séparez une chaîne avec des caractères os x newline). Probablement pas la méthode la plus rapide cependant.

MODIFIER:

Comme les commentaires l'ont correctement souligné, cela supprime également les espaces au début de la ligne ou avant le nouveau saut de ligne. Si vous devez préserver cet espace, utilisez l’une des autres options.

0
Max