Самый простой способ разбить строку на новые строки в .NET?

588

Мне нужно разбить строку на новые строки в .NET, и единственный способ, которым я знаю разбиение строк, - это метод Split, Однако это не позволит мне (легко) расколоться на новой строке, так что это лучший способ сделать это?

  • 2
    Почему бы и нет? Просто разделить на System.Environment.NewLine
  • 15
    Но вы должны обернуть его в строку [] и добавить дополнительный аргумент и ... это просто кажется неуклюжим.
Теги:
string
split

15 ответов

1072
Лучший ответ

Чтобы разбить на строку, вам нужно использовать перегрузку, которая принимает массив строк:

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

Edit:
Если вы хотите обрабатывать различные типы разрывов строк в тексте, вы можете использовать возможность сопоставить несколько строк. Это будет правильно разделено на любой тип разрыва строки и сохранить пустые строки и интервалы в тексте:

string[] lines = theText.Split(
    new[] { "\r\n", "\r", "\n" },
    StringSplitOptions.None
);
  • 0
    Я так и подозревал. Кроме того, вам нужен еще один аргумент StringSplitOptions. Я просто надеялся, что есть менее неуклюжий способ сделать это.
  • 0
    Переместите clunk в свой собственный метод - возможно, в свой собственный класс StringUtils.
Показать ещё 19 комментариев
76

Как насчет использования StringReader?

using (System.IO.StringReader reader = new System.IO.StringReader(input)) {
    string line = reader.ReadLine();
}
  • 7
    Это мой любимый. Я завернул в метод расширения и возвращаю текущую строку: gist.github.com/ronnieoverby/7916886
  • 3
    Это единственное решение без регулярных выражений, которое я нашел для .netcf 3.5
Показать ещё 1 комментарий
32

Вы можете легко разбить свою строку так:

aString.Split(Environment.NewLine.ToCharArray());
  • 40
    В системе, отличной от * nix, которая разделяется на отдельные символы в строке Newline, то есть символы CR и LF. Это приведет к дополнительной пустой строке между каждой строкой.
  • 0
    Поправьте меня, если я ошибаюсь, но разве это не разделит символы \ и n?
Показать ещё 5 комментариев
20

На основании ответа Гуффа в классе расширения используйте:

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

Старайтесь не использовать string.Split для общего решения, потому что вы будете использовать больше памяти везде, где вы используете функцию - исходную строку и разделенную копию, как в памяти. Поверьте мне, что это может быть одной из проблем, когда вы начинаете масштабироваться - запустите 32-битное пакетное приложение, обрабатывающее 100 МБ документов, и вы сможете использовать восемь одновременных потоков. Не то, чтобы я был там раньше...

Вместо этого используйте итератор следующим образом:

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

Это позволит вам сделать более эффективный цикл памяти вокруг ваших данных;

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

Конечно, если вы хотите все это в памяти, вы можете это сделать;

var allTheLines = document.SplitToLines.ToArray();
  • 0
    Я был там ... (парсинг больших файлов HTML и нехватка памяти). Да, избегайте строк. Использование string.Split может привести к использованию кучи больших объектов (LOH) - но я не уверен в этом на 100%.
  • 0
    Если вы сделали SplitToLines статическим методом (который кажется вам dd), то как вы можете делать blah.SplitToLines.. например, document.SplitToLines... ?
Показать ещё 1 комментарий
8

Для строковой переменной s:

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

Это использует определение среды для окончаний строки. В Windows окончание строк - CR-LF (возврат каретки, подача строки) или в escape-символы С# \r\n.

Это надежное решение, потому что если вы перекомпилируете строки с String.Join, это будет равно вашей исходной строке:

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

Что не делать:

  • Используйте StringSplitOptions.RemoveEmptyEntries, потому что это нарушит разметку, такую ​​как Markdown, где пустые строки имеют синтаксическую цель.
  • Разделить на разделитель new char[]{Environment.NewLine}, потому что в Windows это создаст один пустой строковый элемент для каждой новой строки.
  • 0
    В основном тот же ответ здесь, что и самый высокий, принятый, но у него есть хороший юнит-тест и предостережения.
6

Regex также является опцией:

    private string[] SplitStringByLineFeed(string inpString)
    {
        string[] locResult = Regex.Split(inpString, "[\r\n]+");
        return locResult;
    }
  • 6
    Если вы хотите точно сопоставить строки, сохраняя пустые строки, эта строка регулярного выражения будет лучше: "\r?\n" .
4

Просто подумал, что добавлю свои два бита, потому что другие решения по этому вопросу не попадают в классификацию многократного использования и не удобны. Следующий блок кода расширяет объект string, чтобы он был доступен как естественный метод при работе со строками.

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

Теперь вы можете использовать функцию .Split() из любой строки следующим образом:

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 param. when omitted it is
// set to StringSplitOptions.None
result = foo.Split("-", StringSplitOptions.RemoveEmptyEntries);

Чтобы разбить на новую строку char, просто передайте "\n" или "\r\n" в качестве параметра разделителя.

Комментарий: Было бы неплохо, если бы Microsoft реализовала эту перегрузку.

  • 0
    Environment.Newline предпочтительнее жесткого кодирования \n или \r\n .
  • 0
    @MichaelBlackburn - это неверное утверждение, потому что нет контекста. Environment.Newline предназначен для кроссплатформенной совместимости, а не для работы с файлами, использующими другие окончания строк, чем в текущей операционной системе. Смотрите здесь для получения дополнительной информации , так что это действительно зависит от того, с чем работает разработчик. Использование Environment.Newline гарантирует отсутствие согласованности в типе возврата строки между ОС, где «жесткое кодирование» дает разработчику полный контроль.
Показать ещё 2 комментария
4

В настоящее время я использую эту функцию (на основе других ответов) в VB.NET:

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

Он сначала пытается разбить локальную новую строку платформы, а затем возвращается к каждой возможной новой строке.

Мне нужно только это внутри одного класса. Если это изменится, я, вероятно, сделаю это Public и перенесет его в класс утилиты и, возможно, даже сделаю его методом расширения.

Здесь, как присоединиться к строкам, для хорошей меры:

Private Shared Function JoinLines(lines As IEnumerable(Of String)) As String
    Return String.Join(Environment.NewLine, lines)
End Function
  • 0
    @ Самуил - обратите внимание на цитаты. Они на самом деле имеют это значение. "\r" = возврат. "\r\n" = возврат + новая строка. (пожалуйста, просмотрите этот пост и принятое решение здесь
  • 0
    @ Краанг Хмм .. Я давно не работал с .NET. Я был бы удивлен, если бы так много людей проголосовали за неправильный ответ. Я вижу, что тоже прокомментировал ответ Гуффы и получил там разъяснения. Я удалил свой комментарий к этому ответу. Спасибо за внимание.
2

Ну, на самом деле раскол должен делать:

//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
    Параметр RemoveEmptyEntries удалит пустые строки из текста. Это может быть желательно в некоторых ситуациях, но простой разделитель должен сохранять пустые строки.
  • 0
    да, вы правы, я просто сделал это предположение, что ... ну, пустые строки не интересны;)
1
string[] lines = text.Split(
  Environment.NewLine.ToCharArray(), 
  StringSplitOptions.RemoveEmptyStrings);

Параметр RemoveEmptyStrings гарантирует, что у вас нет пустых записей из-за\n, следующих за \r

(Изменить, чтобы отражать комментарии:) Обратите внимание, что он также отбросит в тексте пустые строки. Обычно это то, что я хочу, но это может быть не ваше требование.

  • 0
    Параметры RemoveEmptyStrings также удаляют пустые строки, поэтому они не будут работать должным образом, если в тексте есть пустые строки.
  • 0
    Возможно, вы хотите сохранить настоящие пустые строки: \ r \ n \ r \ n
0

Я не знал о Environment.Newline, но я думаю, это очень хорошее решение.

Моя попытка была бы:

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

Дополнительный .Trim удаляет любые \r или\n, которые могут быть все еще присутствуют (например, при работе с окнами, но разделяя строку символами os x newline). Вероятно, это не самый быстрый способ.

EDIT:

Как правильно отметили комментарии, это также удаляет любые пробелы в начале строки или перед новой подачей строки. Если вам нужно сохранить этот пробел, используйте один из других вариантов.

  • 0
    Обрезка также удалит все пробелы в начале и конце строк, например отступ.
  • 0
    «.Trim удаляет все \ r или \ n, которые могут все еще присутствовать» - ой. Почему бы не написать надежный код вместо этого?
Показать ещё 2 комментария
-1

Очень просто, на самом деле.

VB.NET:

Private Function SplitOnNewLine(input as String) As String
    Return input.Split(Environment.NewLine)
End Function

С#:

string splitOnNewLine(string input)
{
    return input.split(environment.newline);
}
  • 2
    Совершенно неправильно и не работает. Кроме того, в C # это Environment.NewLine как и в VB.
-1
// using System.IO;

string textToSplit;

  if(textToSplit!=null)
   {
    List<string> lines = new List<string>();
    using (StringReader reader = new StringReader(textToSplit))
    {
        for (string line = reader.ReadLine(); line != null;line = reader.ReadLine())
        {
            lines.Add(line);
        }
    }
   }
-2

Глупый ответ: напишите во временный файл, чтобы вы могли использовать почтенный File.ReadLines

var s = "Hello\r\nWorld";
var path = Path.GetTempFileName();
using (var writer = new StreamWriter(path))
{
    writer.Write(s);
}
var lines = File.ReadLines(path);
  • 0
    Избегайте var , так как он не определяет тип переменной, поэтому вы можете не понимать, как использовать этот объект или что этот объект представляет. Кроме того, это показывает написание строк и даже не указывает имя файла, поэтому я сомневаюсь, что это сработает. Тогда при чтении путь к файлу опять не указывается. Предполагая, что path является C:\Temp\test.txt , вы должны иметь string[] lines = File.ReadLines(path); ,
  • 0
    @vapcguy что я только что прочитал? - Я бы порекомендовал перечитать пост или отладить его в консольной программе, потому что все, что вы сказали, просто неправильно | путь установлен на Path.GetTempFileName | var является распространенным и рекомендуемым определением в C # - кстати, оно определяет тип переменной ...... РЕДАКТИРОВАТЬ: я не говорю, что это хорошее решение
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню