关于C#:在.NET中分割换行字符串的最简单方法?

Easiest way to split a string on newlines in .NET?

我需要在.NET中将一个字符串拆分为新行,我知道的唯一拆分字符串的方法是使用split方法。然而,这不允许我(很容易)在新行上拆分,那么最好的方法是什么呢?


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

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

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

1
2
3
4
5
6
7
8
string[] lines = theText.Split(
    new[] {"

"
,"
"
,"
"
},
    StringSplitOptions.None
);


使用StringReader怎么样?

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


您应该能够很容易地拆分字符串,比如:

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


尽量避免使用string.split作为一般的解决方案,因为在使用函数的任何地方都会使用更多的内存——原始字符串和split copy,都在内存中。相信我,当您开始扩展时,这可能是一个非常棘手的问题——运行一个32位的批处理应用程序来处理100MB的文档,然后您将在8个并发线程上死记硬背。不是说我以前去过那里…

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    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;
            }
        }
    }

这将允许您围绕数据进行更高效的内存循环;

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

当然,如果你想要所有的记忆,你可以这样做;

1
var allTheLines = document.SplitToLines.ToArray();


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

1
2
3
4
5
6
public static string[] Lines(this string source) {
    return source.Split(new string[] {"

"
,"
"
}, StringSplitOptions.None);
}

对于字符串变量s

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

这将使用环境中的行尾定义。在Windows上,行尾是CR-LF(回车、换行)或C的转义字符

中的行尾。

这是一个可靠的解决方案,因为如果您用String.Join重新组合行,这等于原始字符串:

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

不该做什么:

  • 使用StringSplitOptions.RemoveEmptyEntries,因为这将破坏标记,例如标记,其中空行具有句法目的。
  • 在分隔符new char[]{Environment.NewLine}上拆分,因为在Windows中,这将为每个新行创建一个空字符串元素。


Regex也是一个选项:

1
2
3
4
5
6
7
    private string[] SplitStringByLineFeed(string inpString)
    {
        string[] locResult = Regex.Split(inpString,"[

]+"
);
        return locResult;
    }


我只是想添加我的两个部分,因为这个问题的其他解决方案不属于可重用代码分类,而且不方便。下面的代码块扩展了string对象,以便在处理字符串时作为自然方法使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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()函数:

1
2
3
4
5
6
7
8
9
10
11
12
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);

要在换行字符上拆分,只需将"
"
"

"作为分隔符参数传递。

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


我目前正在vb.net中使用此函数(基于其他答案):

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

它首先尝试在平台上拆分本地换行,然后返回到每个可能的换行。

到目前为止,我只需要在一节课上学这个。如果这改变了,我可能会使这个Public并将其移动到一个实用程序类,甚至可能使它成为一个扩展方法。

以下是如何将这些线连接起来,以便更好地测量:

1
2
3
Private Shared Function JoinLines(lines As IEnumerable(Of String)) As String
    Return String.Join(Environment.NewLine, lines)
End Function


好吧,事实上,分割应该做到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//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]);
}


1
2
3
string[] lines = text.Split(
  Environment.NewLine.ToCharArray(),
  StringSplitOptions.RemoveEmptyStrings);

removeEmptyStrings选项将确保您没有空条目,因为

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


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

我的尝试是:

1
2
3
4
5
6
        string str ="Test Me

Test Me
Test Me"
;
        var splitted = str.Split('
'
).Select(s => s.Trim()).ToArray();

additional.trim删除可能仍然存在的任何
或(例如,在Windows上,但使用OS X换行符拆分字符串时)。可能不是最快的方法。

编辑:

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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 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

1
2
3
4
5
6
7
8
9
var s ="Hello

World"
;
var path = Path.GetTempFileName();
using (var writer = new StreamWriter(path))
{
    writer.Write(s);
}
var lines = File.ReadLines(path);


其实很简单。

VB.NET:

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

C:

1
2
3
4
string splitOnNewLine(string input)
{
    return input.split(environment.newline);
}