在. NET中的换行符上拆分字符串的最简单方法?

我需要在. NET中将字符串拆分为换行符,我知道拆分字符串的唯一方法是使用斯普利特方法。然而,这不允许我(轻松)在换行符上拆分,那么最好的方法是什么?

689150 次浏览

要对字符串进行拆分,您需要使用接受字符串数组的重载:

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

编辑:
如果您想处理文本中不同类型的换行符,您可以使用匹配多个字符串的功能。这将正确分割任何类型的换行符,并保留文本中的空行和行间距:

string[] lines = theText.Split(new string[] { "\r\n", "\r", "\n" },StringSplitOptions.None);

你应该能够很容易地拆分字符串,如下所示:

aString.Split(Environment.NewLine.ToCharArray());

我不知道环境. Newline,但我想这是一个很好的解决方案。

我的尝试将是:

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

附加的. trim删除可能仍然存在的任何\r或\n(例如,在windows上但使用os x换行符拆分字符串时)。可能不是最快的方法。

编辑:

正如注释正确指出的那样,这也会删除行首或新行提要之前的任何空格。如果您需要保留该空格,请使用其他选项之一。

那么,实际上拆分应该做的是:

//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 linesstring[] 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);

删除空字符串类型选项将确保由于\n跟随\r而没有空条目

(编辑以反映注释:)请注意,它也会丢弃文本中真正的空行。这通常是我想要的,但可能不是你的要求。

根据Guffa的回答,在扩展类中,使用:

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

对于字符串变量s

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

这使用您的环境对行尾的定义。在Windows上,行尾是CR-LF(回车、换行)或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上,这将为每个新行创建一个空字符串元素。

愚蠢的回答:写入临时文件,以便您可以使用古老的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);

如何使用StringReader

using (System.IO.StringReader reader = new System.IO.StringReader(input)) {string line = reader.ReadLine();}

Regex也是一个选项:

    private string[] SplitStringByLineFeed(string inpString){string[] locResult = Regex.Split(inpString, "[\r\n]+");return locResult;}

我目前在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 StringReturn String.Join(Environment.NewLine, lines)End Function
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);}}}

尽量避免使用string. Split作为通用解决方案,因为在使用该函数的任何地方都会使用更多内存——原始字符串和拆分副本,都在内存中。相信我,当你开始扩展时,这可能是一个大问题——运行一个32位批处理应用程序处理100MB文档,你会在八个并发线程中耗尽。我以前没有遇到过这种情况……

相反,使用这样的迭代器;

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

我只是想添加我的两位,因为这个问题的其他解决方案不属于可重用代码分类,并且不方便。

下面的代码块扩展了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 delimiterresult = 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.Noneresult = foo.Split("-", StringSplitOptions.RemoveEmptyEntries);

要在换行符上拆分,只需传递"\n""\r\n"作为分隔符参数。

评论:如果微软实现了这个重载,那就太好了。

很容易,实际上。

VB.NET:

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

C#:

string splitOnNewLine(string input){return input.split(environment.newline);}

这里的例子很棒,帮助我解决了当前的“挑战”,即以更具可读性的方式拆分RSA密钥。基于Steve Coopers解决方案:

    string Splitstring(string txt, int n = 120, string AddBefore = "", string AddAfterExtra = ""){//Spit each string into a n-line length list of stringsvar 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 restif(txt.Length > ((txt.Length / n)*n) )Lines.Add(txt.Substring((txt.Length/n)*n));
//Create return text, with extrasstring txtReturn = "";foreach (string Line in Lines)txtReturn += AddBefore + Line + AddAfterExtra +  Environment.NewLine;return txtReturn;}

呈现一个具有33个字符宽度和引号的RSA键,然后简单地

Console.WriteLine(Splitstring(RSAPubKey, 33, "\"", "\""));

输出:

拆分字符串的输出();

希望有人觉得有用……

从. NET 6开始,我们可以使用新的字符串。替换行尾()方法来规范跨平台的行结尾,所以这些天我发现这是最简单的方法:

var lines = input.ReplaceLineEndings().Split(Environment.NewLine, StringSplitOptions.None);