簡體   English   中英

"在 .NET 中以換行符分割字符串的最簡單方法?"

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

要拆分字符串,您需要使用采用字符串數組的重載:

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

編輯:
如果要處理文本中不同類型的換行符,可以使用匹配多個字符串的功能。 這將在任一類型的換行符上正確拆分,並在文本中保留空行和間距:

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

盡量避免使用 string.Split 作為通用解決方案,因為在使用該函數的任何地方都會使用更多內存——原始字符串和拆分副本都在內存中。 相信我,當您開始擴展時,這可能是一個大問題——運行一個 32 位批處理應用程序處理 100MB 文檔,您將在 8 個並發線程中崩潰。 不是我以前去過那里...

相反,使用這樣的迭代器;

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

根據 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重新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 上,這將為每個新行創建一個空字符串元素。

正則表達式也是一種選擇:

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

我只是想我會添加我的兩位,因為這個問題的其他解決方案不屬於可重用代碼分類並且不方便。

以下代碼塊擴展了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 parameter. When omitted it is
// set to StringSplitOptions.None
result = foo.Split("-", StringSplitOptions.RemoveEmptyEntries);

要拆分換行符,只需將"\\n""\\r\\n"作為分隔符參數傳遞。

評論:如果 Microsoft 實現此重載,那就太好了。

我目前在 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

好吧,實際上 split 應該這樣做:

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

我不知道 Environment.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 換行符拆分字符串時)。 雖然可能不是最快的方法。

編輯:

正如評論正確指出的那樣,這也會刪除行首或新換行符之前的任何空格。 如果您需要保留該空格,請使用其他選項之一。

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

RemoveEmptyStrings選項將確保您沒有由於 \\n 跟隨 \\r 而導致的空條目

(編輯以反映評論:)請注意,它還會丟棄文本中的真正空行。 這通常是我想要的,但可能不是您的要求。

這里的例子很棒,幫助我解決了當前的“挑戰”,即拆分 RSA 密鑰以更易讀的方式呈現。 基於Steve Coopers 的解決方案:

    string Splitstring(string txt, int n = 120, string AddBefore = "", string AddAfterExtra = "")
    {
        //Spit each string into a n-line length list of strings
        var 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 rest
        if(txt.Length > ((txt.Length / n)*n) )
            Lines.Add(txt.Substring((txt.Length/n)*n));

        //Create return text, with extras
        string txtReturn = "";
        foreach (string Line in Lines)
            txtReturn += AddBefore + Line + AddAfterExtra +  Environment.NewLine;
        return txtReturn;
    }

然后簡單地呈現具有 33 個字符寬度和引號的 RSA 密鑰

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

輸出:

Splitstring() 的輸出;

希望有人覺得它有用...

從 .NET 6 開始,我們可以使用新的String.ReplaceLineEndings()方法來規范化跨平台行尾,所以這些天我發現這是最簡單的方法:

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

愚蠢的答案:寫入一個臨時文件,以便您可以使用古老的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);
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);
        }
    }
}

實際上很容易。

VB.NET:

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

C#:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM