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

RCI*_*CIX 755 .net c# string split

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

Guf*_*ffa 1328

要拆分字符串,您需要使用带有字符串数组的重载:

string[] lines = theText.Split(
    new[] { Environment.NewLine },
    StringSplitOptions.None
);
Run Code Online (Sandbox Code Playgroud)

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

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

  • @Leandro:`Environment.NewLine`属性包含系统的默认换行符.例如,对于Windows系统,它将是"\ r \n"`. (4认同)
  • @RCIX:向方法发送正确的参数有点尴尬,因为你将它用于比它能够简单得多的东西.至少它在那里,在框架2之前你必须使用正则表达式或构建自己的拆分例程来拆分字符串... (3认同)
  • @Leandro:一个猜测是程序在`\n`上分裂,在每行的末尾留下一个`\ r`,然后在它们之间输出一行`\ r \n`. (3认同)
  • @Samuel:`\ r`和`\n`转义序列(等等)对C#编译器有特殊意义.VB没有那些转义序列,所以使用那些常量代替. (3认同)
  • 如果您想接受来自许多不同操作系统的文件,您还可以在分隔符列表的开头添加“\n\r”并在末尾添加“\r”。不过,我不确定性能是否值得。(http://en.wikipedia.org/wiki/Newline) (2认同)

Clé*_*ent 111

怎么用StringReader

using (System.IO.StringReader reader = new System.IO.StringReader(input)) {
    string line = reader.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)

  • 这是我最喜欢的.我用扩展方法包装并收益返回当前行:https://gist.github.com/ronnieoverby/7916886 (9认同)
  • 特别好,当输入很大并将其全部复制到数组时会变得缓慢/占用大量内存. (7认同)
  • 这是我为.netcf 3.5找到的唯一非正则表达式解决方案 (3认同)
  • 正如所写,这个答案只读取第一行。请参阅 [Steve Cooper 的答案](/sf/answers/1638561431/) 了解应添加到此答案中的“while”循环。 (3认同)

nik*_*d23 44

你应该可以很容易地分割你的字符串,如下所示:

aString.Split(Environment.NewLine.ToCharArray());
Run Code Online (Sandbox Code Playgroud)

  • 在非*nix系统上,将拆分Newline字符串中的单独字符,即CR和LF字符.这将导致每行之间有一个额外的空字符串. (44认同)
  • @Ruben:不,不会.Serge已经建议在他的回答中,我已经解释过它也会删除原始文本中应该保留的空行. (16认同)
  • 如果你添加参数StringSplitOptions.RemoveEmptyEntries,那么这将完美地工作. (9认同)
  • @RCIX:不,\ r和\n代码代表单个字符.字符串"\ r \n"是两个字符,而不是四个字符. (7认同)
  • @Guffa当然,假设您实际上想保留空行。就我而言,我没有,所以这是完美的。但是,是的,如果您试图为用户保留空行数据,那么您将不得不做一些比这更不优雅的事情。 (2认同)

Ste*_*per 29

尽量避免使用string.Split作为一般解决方案,因为在使用该函数的任何地方都会使用更多内存 - 原始字符串和拆分副本,都在内存中.请相信我,当你开始扩展时,这可能是一个问题 - 运行一个处理100MB文件的32位批处理应用程序,你将在八个并发线程中废弃.不是说我以前去过那里......

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

    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;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

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

foreach(var line in document.SplitToLines()) 
{
    // one line at a time...
}
Run Code Online (Sandbox Code Playgroud)

当然,如果你想要所有内存,你可以这样做;

var allTheLines = document.SplitToLines.ToArray();
Run Code Online (Sandbox Code Playgroud)


Erw*_*yer 24

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

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


Dan*_*erg 12

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

var lines = input
  .ReplaceLineEndings()
  .Split(Environment.NewLine, StringSplitOptions.None);
Run Code Online (Sandbox Code Playgroud)


Col*_*nic 8

对于字符串变量s:

s.Split(new string[]{Environment.NewLine},StringSplitOptions.None)
Run Code Online (Sandbox Code Playgroud)

这使用了您的环境对行结尾的定义.在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);
Run Code Online (Sandbox Code Playgroud)

什么不该做:

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


小智 7

正则表达式也是一个选项:

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

  • 如果你想准确匹配线,保留空白行,这个正则表达式字符串会更好:`"\ r?\n"`. (6认同)

Kra*_*ime 6

只是想我会添加我的两位,因为这个问题的其他解决方案不属于可重用的代码分类并且不方便.下面的代码块扩展了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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您现在可以使用.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 parameter. When omitted it is
// set to StringSplitOptions.None
result = foo.Split("-", StringSplitOptions.RemoveEmptyEntries);
Run Code Online (Sandbox Code Playgroud)

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

评论: 如果微软实现这种过载会很好.

  • @MichaelBlackburn - 这是一个无效的陈述,因为没有上下文。`Environment.Newline` 是为了跨平台兼容性,而不是为了使用与当前操作系统不同的行终止符来处理文件。[请参阅此处了解更多信息](/sf/answers/1601497341/),因此这实际上取决于开发人员正在使用的内容。使用“Environment.Newline”可确保操作系统之间的行返回类型没有一致性,其中“硬编码”赋予开发人员完全控制权。 (4认同)
  • @MichaelBlackburn - 你没必要粗鲁。我只是提供信息。`.Newline` 不是魔术,在引擎盖下它只是上面提供的字符串,基于它是在 unix 上还是在 Windows 上运行的开关。最安全的选择是首先对所有 "\r\n" 进行字符串替换,然后在 "\n" 上拆分。使用 `.Newline` 失败的地方是当您使用其他程序保存的文件时,这些程序使用不同的换行方法。如果您知道每次读取文件时总是使用当前操作系统的换行符,那么它运行良好。 (2认同)