[英]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, "\"", "\""));
輸出:
希望有人覺得它有用...
從 .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.