Самый простой способ разбить строку на новые строки в.NET?
Мне нужно разбить строку на новые строки в.NET, и единственный известный мне способ разбить строки - это метод Split. Однако это не позволит мне (легко) разбить на новую строку, так каков наилучший способ сделать это?
17 ответов
Чтобы разбить строку, вам нужно использовать перегрузку, которая принимает массив строк:
string[] lines = theText.Split(
new[] { Environment.NewLine },
StringSplitOptions.None
);
Редактировать:
Если вы хотите обрабатывать различные типы разрывов строк в тексте, вы можете использовать возможность сопоставления нескольких строк. Это правильно разделит любой тип переноса строки и сохранит пустые строки и интервалы в тексте:
string[] lines = theText.Split(
new[] { "\r\n", "\r", "\n" },
StringSplitOptions.None
);
Как насчет использования StringReader
?
using (System.IO.StringReader reader = new System.IO.StringReader(input)) {
string line = reader.ReadLine();
}
Старайтесь избегать использования 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();
Вы должны быть в состоянии разбить вашу строку довольно легко, например так:
aString.Split(Environment.NewLine.ToCharArray());
Основываясь на ответе Гуффы, в классе расширения используйте:
public static string[] Lines(this string source) {
return source.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
}
Начиная с .NET 6 мы можем использовать новый метод String.ReplaceLineEndings() для канонизации кроссплатформенных окончаний строк, поэтому в наши дни я считаю, что это самый простой способ:
var lines = input
.ReplaceLineEndings()
.Split(Environment.NewLine, StringSplitOptions.None);
Regex также вариант:
private string[] SplitStringByLineFeed(string inpString)
{
string[] locResult = Regex.Split(inpString, "[\r\n]+");
return locResult;
}
Для строковой переменной s
:
s.Split(new string[]{Environment.NewLine},StringSplitOptions.None)
При этом используется определение окончаний строк в вашей среде. В Windows окончание строки - CR-LF (возврат каретки, перевод строки) или escape-символы C# \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 это создаст один пустой строковый элемент для каждой новой строки.
Просто подумал, что добавлю свои два бита, потому что другие решения по этому вопросу не попадают в классификацию кода для повторного использования и не удобны. Следующий блок кода расширяет 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);
Чтобы разделить символ новой строки, просто передайте "\n"
или же "\r\n"
в качестве параметра разделителя.
Комментарий: было бы неплохо, если бы Microsoft реализовала эту перегрузку.
В настоящее время я использую эту функцию (на основе других ответов) в 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
Ну, на самом деле сплит должен сделать:
//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]);
}
string[] lines = text.Split(
Environment.NewLine.ToCharArray(),
StringSplitOptions.RemoveEmptyStrings);
Параметр RemoveEmptyStrings гарантирует, что у вас нет пустых записей из-за \n после \ r
(Изменить, чтобы отразить комментарии:) Обратите внимание, что в тексте также будут отбрасываться подлинные пустые строки Обычно это то, что я хочу, но это не может быть вашим требованием.
Примеры здесь великолепны и помогли мне с текущей "проблемой" разделить ключи RSA, чтобы они были представлены в более удобочитаемом виде. На основе решения Стива Куперса:
string Splitstring(string txt, int n = 120, string AddBefore = "", string AddAfterExtra = "")
{
//Spit each string into a n-line length list of strings
var Lines = Enumerable.Range(0, txt.Length / n).Select(i => txt.Substring(i * n, n)).ToList();
//Check if there are any characters left after split, if so add the rest
if(txt.Length > ((txt.Length / n)*n) )
Lines.Add(txt.Substring((txt.Length/n)*n));
//Create return text, with extras
string txtReturn = "";
foreach (string Line in Lines)
txtReturn += AddBefore + Line + AddAfterExtra + Environment.NewLine;
return txtReturn;
}
Представление RSA-ключа с шириной 33 символа и кавычками тогда просто
Console.WriteLine(Splitstring(RSAPubKey, 33, "\"", "\""));
Вывод:
Надеюсь, кому-то это пригодится...
Я не знал о 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). Вероятно, не самый быстрый метод, хотя.
РЕДАКТИРОВАТЬ:
Как правильно отмечено в комментариях, это также удаляет любые пробелы в начале строки или перед новым переводом строки. Если вам нужно сохранить этот пробел, используйте один из других вариантов.
Глупый ответ: написать во временный файл, чтобы вы могли использовать почтенный 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);
// 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);
}
}
}
Очень просто, на самом деле.
VB.NET:
Private Function SplitOnNewLine(input as String) As String
Return input.Split(Environment.NewLine)
End Function
C#:
string splitOnNewLine(string input)
{
return input.split(environment.newline);
}