170 votes

Meilleur moyen de diviser une chaîne de caractères en lignes

Comment diviser une chaîne de caractères de plusieurs lignes en plusieurs lignes ?

Je connais ce chemin

var result = input.Split("\n\r".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

est un peu moche et perd des lignes vides. Existe-t-il une meilleure solution ?

0 votes

1 votes

J'aime cette solution, mais je ne sais pas comment la rendre plus facile. Le deuxième paramètre supprime les vides, bien sûr.

211voto

Konrad Rudolph Points 231505
  • Si c'est laid, il suffit de supprimer les éléments inutiles. ToCharArray appeler.

  • Si vous voulez diviser par soit \n ou \r vous avez deux options :

    • Utilisez un tableau littéral - mais cela vous donnera des lignes vides pour les fins de ligne de style Windows. \r\n :

      var result = text.Split(new [] { '\r', '\n' });
    • Utilisez une expression régulière, comme indiqué par Bart :

      var result = Regex.Split(text, "\r\n|\r|\n");
  • Si vous voulez préserver les lignes vides, pourquoi dites-vous explicitement à C# de les jeter ? ( StringSplitOptions ) - utiliser StringSplitOptions.None à la place.

2 votes

La suppression de ToCharArray rendra le code spécifique à la plate-forme (NewLine peut être ' \n ')

0 votes

@Kon vous devriez utiliser Environment.NewLine si c'est votre préoccupation. Ou bien voulez-vous dire l'origine du texte, plutôt que le lieu d'exécution ?

1 votes

@Will : au cas où vous feriez référence à moi plutôt qu'à Konstantin : je crois ( fortement ) que le code d'analyse syntaxique devrait s'efforcer de fonctionner sur toutes les plateformes (c'est-à-dire qu'il devrait également lire les fichiers texte qui ont été encodés sur différents que la plate-forme d'exécution). Donc pour l'analyse syntaxique, Environment.NewLine c'est un non sens en ce qui me concerne. En fait, de toutes les solutions possibles, je préfère celle qui utilise des expressions régulières, car elle est la seule à gérer correctement toutes les plateformes sources.

150voto

Jack Points 845
using (StringReader sr = new StringReader(text)) {
    string line;
    while ((line = sr.ReadLine()) != null) {
        // do something
    }
}

14 votes

C'est l'approche la plus propre, à mon avis subjectif.

5 votes

Une idée en termes de performances (par rapport à string.Split ou Regex.Split ) ?

70voto

orad Points 978

Mise à jour : Voir ici pour une solution alternative/asynchrone.


Cela fonctionne très bien et est plus rapide que Regex :

input.Split(new[] {"\r\n", "\r", "\n"}, StringSplitOptions.None)

Il est important d'avoir "\r\n" en premier dans le tableau pour qu'il soit considéré comme un saut de ligne. Ce qui précède donne les mêmes résultats que l'une ou l'autre de ces solutions Regex :

Regex.Split(input, "\r\n|\r|\n")

Regex.Split(input, "\r?\n|\r")

Sauf que Regex s'avère être environ 10 fois plus lent. Voici mon test :

Action<Action> measure = (Action func) => {
    var start = DateTime.Now;
    for (int i = 0; i < 100000; i++) {
        func();
    }
    var duration = DateTime.Now - start;
    Console.WriteLine(duration);
};

var input = "";
for (int i = 0; i < 100; i++)
{
    input += "1 \r2\r\n3\n4\n\r5 \r\n\r\n 6\r7\r 8\r\n";
}

measure(() =>
    input.Split(new[] {"\r\n", "\r", "\n"}, StringSplitOptions.None)
);

measure(() =>
    Regex.Split(input, "\r\n|\r|\n")
);

measure(() =>
    Regex.Split(input, "\r?\n|\r")
);

Sortie :

00:00:03.8527616

00:00:31.8017726

00:00:32.5557128

et voici le Méthode d'extension :

public static class StringExtensionMethods
{
    public static IEnumerable<string> GetLines(this string str, bool removeEmptyLines = false)
    {
        return str.Split(new[] { "\r\n", "\r", "\n" },
            removeEmptyLines ? StringSplitOptions.RemoveEmptyEntries : StringSplitOptions.None);
    }
}

Utilisation :

input.GetLines()      // keeps empty lines

input.GetLines(true)  // removes empty lines

0 votes

Veuillez ajouter quelques détails supplémentaires afin de rendre votre réponse plus utile pour les lecteurs.

0 votes

Terminé. J'ai également ajouté un test pour comparer ses performances avec la solution Regex.

0 votes

Un motif un peu plus rapide en raison de moins de retour en arrière avec la même fonctionnalité si l'on utilise [\r\n]{1,2}

36voto

Bart Kiers Points 79069

Vous pourriez utiliser Regex.Split :

string[] tokens = Regex.Split(input, @"\r?\n|\r");

Edit : ajouté |\r pour tenir compte des terminaisons de ligne Mac (plus anciennes).

0 votes

Cela ne fonctionnera pas sur les fichiers texte de style OS X, car ceux-ci n'utilisent que l'option \r comme fin de ligne.

2 votes

@Konrad Rudolph : AFAIK, ' \r était utilisé sur de très vieux systèmes MacOS et n'est presque plus rencontré. Mais si le PO a besoin d'en tenir compte (ou si je me trompe), alors la regex peut facilement être étendue pour en tenir compte bien sûr : \r ? \n | \r

0 votes

@Bart : Je ne pense pas que vous vous trompez mais je ont J'ai rencontré à plusieurs reprises toutes les fins de ligne possibles dans ma carrière de programmeur.

11voto

Jonas Elfström Points 16453

Si vous voulez garder des lignes vides, il suffit de supprimer les StringSplitOptions.

var result = input.Split(System.Environment.NewLine.ToCharArray());

2 votes

NewLine peut être ' \n et le texte d'entrée peut contenir " \n\r ".

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X