ฉันต้องแยกสตริงออกเป็นบรรทัดใหม่ใน. NET และวิธีเดียวที่ฉันรู้ว่าจะแบ่งสตริงคือด้วยวิธีการแยก อย่างไรก็ตามนั่นจะไม่อนุญาตให้ฉันแยก (ขึ้นบรรทัดใหม่) ได้อย่างง่ายดายดังนั้นวิธีที่ดีที่สุดในการทำคืออะไร
ฉันต้องแยกสตริงออกเป็นบรรทัดใหม่ใน. NET และวิธีเดียวที่ฉันรู้ว่าจะแบ่งสตริงคือด้วยวิธีการแยก อย่างไรก็ตามนั่นจะไม่อนุญาตให้ฉันแยก (ขึ้นบรรทัดใหม่) ได้อย่างง่ายดายดังนั้นวิธีที่ดีที่สุดในการทำคืออะไร
คำตอบ:
ในการแยกสตริงคุณจำเป็นต้องใช้โอเวอร์โหลดที่ใช้อาร์เรย์ของสตริง:
string[] lines = theText.Split(
new[] { Environment.NewLine },
StringSplitOptions.None
);
แก้ไข:
หากคุณต้องการจัดการตัวแบ่งบรรทัดประเภทต่าง ๆ ในข้อความคุณสามารถใช้ความสามารถในการจับคู่มากกว่าหนึ่งสตริง สิ่งนี้จะถูกแบ่งอย่างถูกต้องในการแบ่งบรรทัดทั้งสองประเภทและเก็บรักษาบรรทัดว่างและระยะห่างในข้อความ:
string[] lines = theText.Split(
new[] { "\r\n", "\r", "\n" },
StringSplitOptions.None
);
Environment.NewLine
คุณสมบัติมีการขึ้นบรรทัดใหม่เริ่มต้นสำหรับระบบ สำหรับระบบปฏิบัติการ Windows "\r\n"
ตัวอย่างเช่นมันจะเป็น
\n
ออกจาก\r
ที่ปลายแต่ละบรรทัดแล้วส่งออกบรรทัดที่มี\r\n
ระหว่างพวกเขา
\r
และ\n
escape sequences (ในหมู่อื่น ๆ ) มีความหมายพิเศษกับคอมไพเลอร์ C # VB ไม่มีลำดับการหลีกเลี่ยงเหล่านั้นดังนั้นจึงใช้ค่าคงที่เหล่านั้นแทน
สิ่งที่เกี่ยวกับการใช้StringReader
?
using (System.IO.StringReader reader = new System.IO.StringReader(input)) {
string line = reader.ReadLine();
}
while
วนซ้ำที่ควรเพิ่มในคำตอบนี้
คุณควรจะสามารถแยกสตริงของคุณได้อย่างง่ายดายเช่น:
aString.Split(Environment.NewLine.ToCharArray());
พยายามหลีกเลี่ยงการใช้สตริงแยกสำหรับโซลูชันทั่วไปเนื่องจากคุณจะใช้หน่วยความจำมากขึ้นทุกที่ที่คุณใช้ฟังก์ชั่น - สตริงเดิมและสำเนาแยกทั้งในหน่วยความจำ เชื่อฉันเถอะว่านี่อาจเป็นปัญหาหนึ่งเมื่อคุณเริ่มขยายขนาด - เรียกใช้แอปประมวลผลแบบ 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();
blah.SplitToLines..
เช่นdocument.SplitToLines...
?
this
พารามิเตอร์ทางการทำให้เป็นวิธีการขยาย
ตามคำตอบของ 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 # 's \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
เพราะจะทำให้มาร์กอัปแตกเช่นมาร์กดาวน์ที่บรรทัดว่างมีวัตถุประสงค์ในการสร้างประโยคnew char[]{Environment.NewLine}
เนื่องจากใน Windows จะสร้างองค์ประกอบสตริงว่างหนึ่งรายการสำหรับแต่ละบรรทัดใหม่Regex ยังเป็นตัวเลือก:
private string[] SplitStringByLineFeed(string inpString)
{
string[] locResult = Regex.Split(inpString, "[\r\n]+");
return locResult;
}
"\r?\n"
จะดีกว่า:
ฉันแค่คิดว่าฉันจะเพิ่มสองบิตของฉันเพราะโซลูชันอื่น ๆ ในคำถามนี้ไม่ได้อยู่ในการจำแนกรหัสที่สามารถนำกลับมาใช้ใหม่ได้และไม่สะดวก
บล็อกของรหัสต่อไปนี้ขยาย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 ใช้งานเกินนี้
Environment.Newline
เป็นที่ต้องการการเข้ารหัสที่ยากอย่างใดอย่างหนึ่งหรือ\n
\r\n
Environment.Newline
ใช้สำหรับการทำงานร่วมกันข้ามแพลตฟอร์มไม่ใช่สำหรับการทำงานกับไฟล์ที่ใช้การยุติบรรทัดที่แตกต่างจากระบบปฏิบัติการปัจจุบัน ดูข้อมูลเพิ่มเติมได้ที่นี่ดังนั้นขึ้นอยู่กับสิ่งที่นักพัฒนาทำงานด้วย การใช้Environment.Newline
เพื่อให้แน่ใจว่าไม่มีความสอดคล้องในประเภทการส่งคืนบรรทัดระหว่างระบบปฏิบัติการซึ่ง 'การเข้ารหัสแบบยาก' ให้การควบคุมเต็มรูปแบบแก่นักพัฒนา
.Newline
ไม่ใช่เวทย์มนตร์ภายใต้ประทุนมันเป็นเพียงแค่สายอักขระที่ให้ไว้ข้างต้นขึ้นอยู่กับสวิตช์ของถ้ามันทำงานบนยูนิกซ์หรือบนหน้าต่าง เดิมพันที่ปลอดภัยที่สุดคือการทำสตริงก่อนสำหรับ "\ r \ n" ทั้งหมดแล้วแยกใน "\ n" การใช้.Newline
ล้มเหลวคือเมื่อคุณทำงานกับไฟล์ที่ถูกบันทึกโดยโปรแกรมอื่นที่ใช้วิธีการอื่นในการแบ่งบรรทัด มันทำงานได้ดีถ้าคุณรู้ทุกครั้งที่อ่านไฟล์จะใช้ตัวแบ่งบรรทัดของระบบปฏิบัติการปัจจุบันของคุณเสมอ
foo = foo.Replace("\r\n", "\n"); string[] result = foo.Split('\n');
จะ ฉันเข้าใจถูกต้องหรือไม่ว่านี่ใช้ได้กับทุกแพลตฟอร์มหรือไม่
ขณะนี้ฉันใช้ฟังก์ชันนี้ (ตามคำตอบอื่น ๆ ) ใน 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
"\r"
= return "\r\n"
= return + new line (โปรดอ่านโพสต์นี้และทางออกที่ได้รับการยอมรับที่นี่
ดีจริง ๆ แล้วควรแยก:
//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]);
}
string[] lines = text.Split(
Environment.NewLine.ToCharArray(),
StringSplitOptions.RemoveEmptyStrings);
RemoveEmptyStringsตัวเลือกที่จะทำให้แน่ใจว่าคุณไม่ได้มีรายการที่ว่างเปล่าเนื่องจาก \ n ต่อไปนี้ \ r
(แก้ไขเพื่อสะท้อนความคิดเห็น :) โปรดทราบว่าจะเป็นการลบบรรทัดว่างเปล่าในข้อความด้วย นี่คือสิ่งที่ฉันต้องการ แต่มันอาจไม่ใช่ความต้องการของคุณ
ฉันไม่ทราบเกี่ยวกับสิ่งแวดล้อมบรรทัดใหม่ แต่ฉันเดาว่านี่เป็นวิธีแก้ปัญหาที่ดีมาก
ฉันจะลอง:
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 newline) อาจไม่ใช่วิธีที่เร็วที่สุด
แก้ไข:
เมื่อความคิดเห็นชี้ไปอย่างถูกต้องสิ่งนี้จะลบช่องว่างใด ๆ ที่จุดเริ่มต้นของบรรทัดหรือก่อนป้อนบรรทัดใหม่ หากคุณต้องการรักษาพื้นที่ว่างนั้นใช้หนึ่งในตัวเลือกอื่น ๆ
คำตอบ Silly: เขียนไปที่ไฟล์ชั่วคราวเพื่อให้คุณสามารถใช้เป็นที่เคารพ
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);
var
เนื่องจากมันไม่ได้กำหนดประเภทของตัวแปรดังนั้นคุณอาจไม่เข้าใจวิธีการใช้วัตถุนั้นหรือวัตถุนั้นหมายถึงอะไร นอกจากนี้ยังแสดงการเขียนบรรทัดและไม่ได้ระบุชื่อไฟล์ด้วยดังนั้นฉันสงสัยว่ามันจะใช้งานได้ จากนั้นเมื่ออ่านเส้นทางไม่ได้ระบุพา ธ ไปยังไฟล์อีกครั้ง สมมติว่าpath
เป็นแล้วคุณควรจะมีC:\Temp\test.txt
string[] lines = File.ReadLines(path);
Path.GetTempFileName
ค้นหา msdn.microsoft.com/en-us/library/ ......และมันบอกว่ามันสร้างไฟล์เป็นศูนย์ไบต์และส่งกลับ "เส้นทางแบบเต็มของไฟล์นั้น" ฉันสาบานได้ว่าฉันได้ลองทำสิ่งนี้มาก่อนและมันมีข้อยกเว้นเพราะหาไฟล์ไม่พบ แต่ได้ส่งคืนตำแหน่งโฟลเดอร์แทน ฉันรู้ว่าข้อโต้แย้งในการใช้var
แต่ฉันบอกว่าไม่แนะนำเพราะไม่แสดงว่าวัตถุตัวแปร มันทำให้งงงวยมัน
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
ค#:
string splitOnNewLine(string input)
{
return input.split(environment.newline);
}
Environment.NewLine
เหมือนกับใน VB