Мне нужно разбить строку на новые строки в .NET, и единственный способ, которым я знаю разбиение строк, - это метод Split, Однако это не позволит мне (легко) расколоться на новой строке, так что это лучший способ сделать это?
Чтобы разбить на строку, вам нужно использовать перегрузку, которая принимает массив строк:
string[] lines = theText.Split(
new[] { Environment.NewLine },
StringSplitOptions.None
);
Edit:
Если вы хотите обрабатывать различные типы разрывов строк в тексте, вы можете использовать возможность сопоставить несколько строк. Это будет правильно разделено на любой тип разрыва строки и сохранить пустые строки и интервалы в тексте:
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();
}
Вы можете легко разбить свою строку так:
aString.Split(Environment.NewLine.ToCharArray());
На основании ответа Гуффа в классе расширения используйте:
public static string[] Lines(this string source) {
return source.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
}
Старайтесь не использовать 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();
blah.SplitToLines..
например, document.SplitToLines...
?
Для строковой переменной 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 это создаст один пустой строковый элемент для каждой новой строки.Regex также является опцией:
private string[] SplitStringByLineFeed(string inpString)
{
string[] locResult = Regex.Split(inpString, "[\r\n]+");
return locResult;
}
"\r?\n"
.
Просто подумал, что добавлю свои два бита, потому что другие решения по этому вопросу не попадают в классификацию многократного использования и не удобны. Следующий блок кода расширяет объект 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 реализовала эту перегрузку.
Environment.Newline
предпочтительнее жесткого кодирования \n
или \r\n
.
Environment.Newline
предназначен для кроссплатформенной совместимости, а не для работы с файлами, использующими другие окончания строк, чем в текущей операционной системе. Смотрите здесь для получения дополнительной информации , так что это действительно зависит от того, с чем работает разработчик. Использование Environment.Newline
гарантирует отсутствие согласованности в типе возврата строки между ОС, где «жесткое кодирование» дает разработчику полный контроль.
В настоящее время я использую эту функцию (на основе других ответов) в 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
"\r"
= возврат. "\r\n"
= возврат + новая строка. (пожалуйста, просмотрите этот пост и принятое решение здесь
Ну, на самом деле раскол должен делать:
//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
(Изменить, чтобы отражать комментарии:) Обратите внимание, что он также отбросит в тексте пустые строки. Обычно это то, что я хочу, но это может быть не ваше требование.
Я не знал о 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:
Как правильно отметили комментарии, это также удаляет любые пробелы в начале строки или перед новой подачей строки. Если вам нужно сохранить этот пробел, используйте один из других вариантов.
Очень просто, на самом деле.
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);
}
Environment.NewLine
как и в VB.
// 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);
}
}
}
Глупый ответ: напишите во временный файл, чтобы вы могли использовать почтенный
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);
var
, так как он не определяет тип переменной, поэтому вы можете не понимать, как использовать этот объект или что этот объект представляет. Кроме того, это показывает написание строк и даже не указывает имя файла, поэтому я сомневаюсь, что это сработает. Тогда при чтении путь к файлу опять не указывается. Предполагая, что path
является C:\Temp\test.txt
, вы должны иметь string[] lines = File.ReadLines(path);
,