Самый простой способ разбить строку на новые строки в .NET?
806
Мне нужно разбить строку на новые строки в .NET, и единственный известный мне способ разбить строки - это метод Split . Однако это не позволит мне (легко) разбить на новую строку, так каков наилучший способ сделать это?
Редактировать:
Если вы хотите обрабатывать различные типы разрывов строк в тексте, вы можете использовать возможность сопоставлять более чем одну строку. Это правильно разделит любой тип разрыва строки и сохранит пустые строки и интервалы в тексте:
@RCIX: отправлять правильные параметры в метод немного неудобно, потому что вы используете его для чего-то, что намного проще, чем то, на что он способен. По крайней мере, там, до фреймворка 2 вам приходилось использовать регулярное выражение или создавать собственную подпрограмму расщепления для разбиения на строку ...
Guffa
4
@Leandro: Environment.NewLineсвойство содержит новую строку по умолчанию для системы. Например, для системы Windows это будет "\r\n".
Guffa
3
@Leandro: Одним из предположений может быть то, что программа разделяется, \nоставляя \rточку в конце каждой строки, а затем выводит строки \r\nмежду ними.
Guffa
3
@Samuel: последовательности \rи \nescape (среди прочих) имеют особое значение для компилятора C #. VB не имеет этих escape-последовательностей, поэтому вместо них используются эти константы.
Гуффа
2
Если вы хотите принимать файлы из множества различных ОС, вы также можете добавить «\ n \ r» в начало и «\ r» в конец списка разделителей. Я не уверен, что это стоит того, чтобы ударить по производительности. ( en.wikipedia.org/wiki/Newline )
В системе, отличной от * nix, которая разделяется на отдельные символы в строке Newline, то есть символы CR и LF. Это приведет к дополнительной пустой строке между каждой строкой.
Гуффа
Поправьте меня, если я ошибаюсь, но разве это не разделит символы \ и n?
RCIX
7
@RCIX: Нет, коды \ r и \ n представляют отдельные символы. Строка "\ r \ n" состоит из двух символов, а не четырех.
Гуффа
10
если вы добавите параметр StringSplitOptions.RemoveEmptyEntries, то это будет работать отлично.
Рубен
18
@Ruben: Нет, не будет. Серж уже предложил это в своем ответе, а я уже объяснил, что он также удалит пустые строки в исходном тексте, которые следует сохранить.
Гуффа
34
Старайтесь избегать использования string.Split для общего решения, потому что вы будете использовать больше памяти везде, где вы используете функцию - исходную строку и разделенную копию, как в памяти. Поверьте мне, что это может быть одной из самых серьезных проблем, когда вы начинаете масштабирование - запустите 32-разрядное приложение пакетной обработки, обрабатывающее документы объемом 100 МБ, и вы справитесь с восемью одновременными потоками. Не то чтобы я был там раньше ...
Я был там ... (парсинг больших файлов HTML и нехватка памяти). Да, избегайте строк. Использование string.Split может привести к использованию кучи больших объектов (LOH) - но я не уверен на 100% в этом.
Питер Мортенсен
Если вы сделали SplitToLines статическим методом (который, кажется, вы dd), то как вы можете это сделать, blah.SplitToLines.. например document.SplitToLines...?
Бароп
Ах, я вижу, вы вводите thisформальные параметры, что делает его методом расширения.
Barlop
26
Основываясь на ответе Гуффы, в классе расширения используйте:
При этом используется определение окончаний строк в вашей среде. В Windows окончание строки - CR-LF (возврат каретки, перевод строки) или escape-символы C #\r\n .
Это надежное решение, потому что если вы рекомбинируете строки с String.Join, это равно вашей исходной строке:
var lines = s.Split(newstring[]{Environment.NewLine},StringSplitOptions.None);var reconstituted =String.Join(Environment.NewLine,lines);Debug.Assert(s==reconstituted);
Что не делать:
использование StringSplitOptions.RemoveEmptyEntries , потому что это сломает разметку, такую как Markdown, где пустые строки имеют синтаксическое назначение.
Разделить на разделитель new char[]{Environment.NewLine}, потому что в Windows это создаст один пустой строковый элемент для каждой новой строки.
Если вы хотите , чтобы соответствовать линии точно, сохраняя пустые строки, это регулярное выражение строка будет лучше: "\r?\n".
Рори О'Кейн
7
Я просто подумал, что добавлю свои два бита, потому что другие решения по этому вопросу не попадают в классификацию кода для повторного использования и не удобны.
Следующий блок кода расширяет 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{publicstaticclassStringExtensions{publicstaticstring[]Split(thisstring s,string delimiter,StringSplitOptions options =StringSplitOptions.None){return s.Split(newstring[]{ delimiter }, options);}}}
Теперь вы можете использовать .Split()функцию из любой строки следующим образом:
string[] result;// Pass a string, and the delimiter
result =string.Split("My simple string"," ");// Split an existing string by delimiter onlystring 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);
Чтобы разделить символ новой строки, просто передайте "\n"или "\r\n"в качестве параметра разделителя.
Комментарий: было бы неплохо, если бы Microsoft реализовала эту перегрузку.
Environment.NewlineПредпочтительно , чтобы жесткое кодирование либо \nили \r\n.
Майкл Блэкберн
3
@MichaelBlackburn - это неверное утверждение, потому что нет контекста. Environment.Newlineпредназначен для кроссплатформенной совместимости, а не для работы с файлами, использующими другие окончания строки, чем в текущей операционной системе. Смотрите здесь для получения дополнительной информации , так что это действительно зависит от того, с чем работает разработчик. Использование Environment.Newlineобеспечивает отсутствие согласованности в типе возврата строки между ОС, где «жесткое кодирование» дает разработчику полный контроль.
Краанг Прайм
2
@MichaelBlackburn - Вам не нужно быть грубым. Я просто предоставлял информацию. .Newlineне волшебство, под капотом это просто строки, как указано выше, основанные на переключателе, если он работает на Unix или Windows. Самая безопасная ставка - сначала заменить строку на все "\ r \ n", а затем разделить на "\ n". Когда использование .Newlineне удается, это когда вы работаете с файлами, которые сохранены другими программами, которые используют другой метод для разрывов строк. Это работает хорошо, если вы знаете, что каждый раз, когда файл читается, всегда использует разрывы строк вашей текущей ОС.
Краанг Прайм
То, что я слышу, - это самый читаемый способ (возможно, более интенсивное использование памяти) foo = foo.Replace("\r\n", "\n"); string[] result = foo.Split('\n');. Я правильно понимаю, что это работает на всех платформах?
Джон Доу
4
В настоящее время я использую эту функцию (на основе других ответов) в VB.NET:
Сначала он пытается разделить новую строку на платформе, а затем возвращается к каждой возможной новой строке.
Мне нужно было это только в одном классе. Если это изменится, я, вероятно, сделаю этоPublic и переместу в служебный класс, и, возможно, даже сделаю его методом расширения.
@ Самуил - обратите внимание на цитаты. Они на самом деле имеют это значение. "\r"= возврат "\r\n"= возврат + новая строка. (пожалуйста, просмотрите этот пост и принятое решение здесь
Kraang Prime
@ Краанг Хмм .. Я давно не работал с .NET. Я был бы удивлен, если бы так много людей проголосовали за неправильный ответ. Я вижу, что тоже прокомментировал ответ Гуффы и получил там разъяснения. Я удалил свой комментарий к этому ответу. Спасибо за внимание.
Самуил
2
Ну, на самом деле сплит должен сделать:
//Constructing string...StringBuilder sb =newStringBuilder();
sb.AppendLine("first line");
sb.AppendLine("second line");
sb.AppendLine("third line");string s = sb.ToString();Console.WriteLine(s);//Splitting multiline string into separate linesstring[] splitted = s.Split(newstring[]{System.Environment.NewLine},StringSplitOptions.RemoveEmptyEntries);// Output (separate lines)for(int i =0; i < splitted.Count(); i++){Console.WriteLine("{0}: {1}", i, splitted[i]);}
Параметр RemoveEmptyEntries удалит пустые строки из текста. Это может быть желательно в некоторых ситуациях, но простой разделитель должен сохранять пустые строки.
Гуффа
да, вы правы, я просто сделал это предположение, что ... ну, пустые строки не интересны;)
В RemoveEmptyStrings гарантирует, что у вас нет пустых записей из-за \ n после \ r
(Изменить, чтобы отразить комментарии :) Обратите внимание, что в тексте также будут отбрасываться подлинные пустые строки. Обычно это то, что я хочу, но это не может быть вашим требованием.
Дополнительный .Trim удаляет все \ r или \ n, которые могут все еще присутствовать (например, в окнах, но разделение строки символами новой строки os x). Вероятно, не самый быстрый способ, хотя.
РЕДАКТИРОВАТЬ:
Как правильно отмечено в комментариях, это также удаляет все пробелы в начале строки или перед новой строкой. Если вам нужно сохранить этот пробел, используйте один из других вариантов.
Избегайте var, поскольку он не определяет тип переменной, поэтому вы можете не понимать, как использовать этот объект или что этот объект представляет. Кроме того, это показывает написание строк и даже не указывает имя файла, поэтому я сомневаюсь, что это сработает. Тогда при чтении путь к файлу опять не указывается. Предполагая, что pathэто так C:\Temp\test.txt, вы должны иметь string[] lines = File.ReadLines(path);.
vapcguy
1
@vapcguy что я только что прочитал? - Я бы порекомендовал перечитать пост или отладить его в консольной программе, потому что все, что вы сказали, просто неправильно | путь установлен на Path.GetTempFileName | var является распространенным и рекомендуемым определением в C # - кстати, оно определяет тип переменной ...... РЕДАКТИРОВАТЬ: Я не говорю, что это хорошее решение
koanbock
@koanbock Хорошо, поэтому я посмотрел Path.GetTempFileNamemsdn.microsoft.com/en-us/library/… и там написано, что он создает файл с нулевым байтом и возвращает «полный путь к этому файлу». Я мог поклясться, что пытался сделать это раньше, и это дало исключение, потому что он не нашел файл, а вместо этого вернул расположение папки. Я знаю аргументы для использования var, но я бы сказал, что это НЕ рекомендуется, потому что он не показывает, что такое переменный объект. Это запутывает это.
vapcguy
-3
using System.IO;string textToSplit;if(textToSplit !=null){List<string> lines =newList<string>();
using (StringReader reader =newStringReader(textToSplit)){for(string line = reader.ReadLine(); line !=null; line = reader.ReadLine()){
lines.Add(line);}}}
Ответы:
Чтобы разбить строку, вам нужно использовать перегрузку, которая принимает массив строк:
Редактировать:
Если вы хотите обрабатывать различные типы разрывов строк в тексте, вы можете использовать возможность сопоставлять более чем одну строку. Это правильно разделит любой тип разрыва строки и сохранит пустые строки и интервалы в тексте:
источник
Environment.NewLine
свойство содержит новую строку по умолчанию для системы. Например, для системы Windows это будет"\r\n"
.\n
оставляя\r
точку в конце каждой строки, а затем выводит строки\r\n
между ними.\r
и\n
escape (среди прочих) имеют особое значение для компилятора C #. VB не имеет этих escape-последовательностей, поэтому вместо них используются эти константы.Как насчет использования
StringReader
?источник
while
цикла, который должен быть добавлен к этому ответу.Вы должны быть в состоянии разбить вашу строку довольно легко, например так:
источник
Старайтесь избегать использования string.Split для общего решения, потому что вы будете использовать больше памяти везде, где вы используете функцию - исходную строку и разделенную копию, как в памяти. Поверьте мне, что это может быть одной из самых серьезных проблем, когда вы начинаете масштабирование - запустите 32-разрядное приложение пакетной обработки, обрабатывающее документы объемом 100 МБ, и вы справитесь с восемью одновременными потоками. Не то чтобы я был там раньше ...
Вместо этого используйте такой итератор;
Это позволит вам сделать более эффективный цикл памяти вокруг ваших данных;
Конечно, если вы хотите все это в памяти, вы можете сделать это;
источник
blah.SplitToLines..
напримерdocument.SplitToLines...
?this
формальные параметры, что делает его методом расширения.Основываясь на ответе Гуффы, в классе расширения используйте:
источник
Для строковой переменной
s
:При этом используется определение окончаний строк в вашей среде. В Windows окончание строки - CR-LF (возврат каретки, перевод строки) или escape-символы C #
\r\n
.Это надежное решение, потому что если вы рекомбинируете строки с
String.Join
, это равно вашей исходной строке:Что не делать:
StringSplitOptions.RemoveEmptyEntries
, потому что это сломает разметку, такую как Markdown, где пустые строки имеют синтаксическое назначение.new char[]{Environment.NewLine}
, потому что в Windows это создаст один пустой строковый элемент для каждой новой строки.источник
Regex также вариант:
источник
"\r?\n"
.Я просто подумал, что добавлю свои два бита, потому что другие решения по этому вопросу не попадают в классификацию кода для повторного использования и не удобны.
Следующий блок кода расширяет
string
объект, чтобы он был доступен как естественный метод при работе со строками.Теперь вы можете использовать
.Split()
функцию из любой строки следующим образом:Чтобы разделить символ новой строки, просто передайте
"\n"
или"\r\n"
в качестве параметра разделителя.Комментарий: было бы неплохо, если бы Microsoft реализовала эту перегрузку.
источник
Environment.Newline
Предпочтительно , чтобы жесткое кодирование либо\n
или\r\n
.Environment.Newline
предназначен для кроссплатформенной совместимости, а не для работы с файлами, использующими другие окончания строки, чем в текущей операционной системе. Смотрите здесь для получения дополнительной информации , так что это действительно зависит от того, с чем работает разработчик. ИспользованиеEnvironment.Newline
обеспечивает отсутствие согласованности в типе возврата строки между ОС, где «жесткое кодирование» дает разработчику полный контроль..Newline
не волшебство, под капотом это просто строки, как указано выше, основанные на переключателе, если он работает на Unix или Windows. Самая безопасная ставка - сначала заменить строку на все "\ r \ n", а затем разделить на "\ n". Когда использование.Newline
не удается, это когда вы работаете с файлами, которые сохранены другими программами, которые используют другой метод для разрывов строк. Это работает хорошо, если вы знаете, что каждый раз, когда файл читается, всегда использует разрывы строк вашей текущей ОС.foo = foo.Replace("\r\n", "\n"); string[] result = foo.Split('\n');
. Я правильно понимаю, что это работает на всех платформах?В настоящее время я использую эту функцию (на основе других ответов) в VB.NET:
Сначала он пытается разделить новую строку на платформе, а затем возвращается к каждой возможной новой строке.
Мне нужно было это только в одном классе. Если это изменится, я, вероятно, сделаю это
Public
и переместу в служебный класс, и, возможно, даже сделаю его методом расширения.Вот, как объединить строки, для хорошей меры:
источник
"\r"
= возврат"\r\n"
= возврат + новая строка. (пожалуйста, просмотрите этот пост и принятое решение здесьНу, на самом деле сплит должен сделать:
источник
В RemoveEmptyStrings гарантирует, что у вас нет пустых записей из-за \ n после \ r
(Изменить, чтобы отразить комментарии :) Обратите внимание, что в тексте также будут отбрасываться подлинные пустые строки. Обычно это то, что я хочу, но это не может быть вашим требованием.
источник
Я не знал о Environment.Newline, но, думаю, это очень хорошее решение.
Моя попытка была бы:
Дополнительный .Trim удаляет все \ r или \ n, которые могут все еще присутствовать (например, в окнах, но разделение строки символами новой строки os x). Вероятно, не самый быстрый способ, хотя.
РЕДАКТИРОВАТЬ:
Как правильно отмечено в комментариях, это также удаляет все пробелы в начале строки или перед новой строкой. Если вам нужно сохранить этот пробел, используйте один из других вариантов.
источник
Глупый ответ: написать во временный файл, чтобы вы могли использовать почтенный
File.ReadLines
источник
var
, поскольку он не определяет тип переменной, поэтому вы можете не понимать, как использовать этот объект или что этот объект представляет. Кроме того, это показывает написание строк и даже не указывает имя файла, поэтому я сомневаюсь, что это сработает. Тогда при чтении путь к файлу опять не указывается. Предполагая, чтоpath
это такC:\Temp\test.txt
, вы должны иметьstring[] lines = File.ReadLines(path);
.Path.GetTempFileName
msdn.microsoft.com/en-us/library/… и там написано, что он создает файл с нулевым байтом и возвращает «полный путь к этому файлу». Я мог поклясться, что пытался сделать это раньше, и это дало исключение, потому что он не нашел файл, а вместо этого вернул расположение папки. Я знаю аргументы для использованияvar
, но я бы сказал, что это НЕ рекомендуется, потому что он не показывает, что такое переменный объект. Это запутывает это.источник
Очень просто, на самом деле.
VB.NET:
C #:
источник
Environment.NewLine
же, как в VB.