Tôi cần chia một chuỗi thành các dòng mới trong .NET và cách duy nhất tôi biết để phân tách chuỗi là với phương thức Split . Tuy nhiên, điều đó sẽ không cho phép tôi (dễ dàng) phân chia trên một dòng mới, vậy cách tốt nhất để làm điều đó là gì?
Tôi cần chia một chuỗi thành các dòng mới trong .NET và cách duy nhất tôi biết để phân tách chuỗi là với phương thức Split . Tuy nhiên, điều đó sẽ không cho phép tôi (dễ dàng) phân chia trên một dòng mới, vậy cách tốt nhất để làm điều đó là gì?
Câu trả lời:
Để phân chia trên một chuỗi, bạn cần sử dụng quá tải cần một mảng các chuỗi:
string[] lines = theText.Split(
new[] { Environment.NewLine },
StringSplitOptions.None
);
Chỉnh sửa:
Nếu bạn muốn xử lý các loại ngắt dòng khác nhau trong một văn bản, bạn có thể sử dụng khả năng khớp nhiều hơn một chuỗi. Điều này sẽ phân chia chính xác trên một trong hai loại ngắt dòng và bảo toàn các dòng trống và khoảng cách trong văn bản:
string[] lines = theText.Split(
new[] { "\r\n", "\r", "\n" },
StringSplitOptions.None
);
Environment.NewLine
Thuộc tính chứa dòng mới mặc định cho hệ thống. Đối với một hệ thống Windows chẳng hạn "\r\n"
.
\n
để lại một dòng \r
ở cuối mỗi dòng, sau đó xuất ra các dòng có một \r\n
giữa chúng.
\r
và \n
thoát (trong số các chuỗi khác) có ý nghĩa đặc biệt đối với trình biên dịch C #. VB không có các chuỗi thoát đó, vì vậy có các hằng số được sử dụng thay thế.
Còn việc sử dụng a StringReader
thì sao?
using (System.IO.StringReader reader = new System.IO.StringReader(input)) {
string line = reader.ReadLine();
}
while
vòng lặp nên được thêm vào câu trả lời này.
Bạn sẽ có thể phân tách chuỗi của bạn khá dễ dàng, như vậy:
aString.Split(Environment.NewLine.ToCharArray());
Cố gắng tránh sử dụng chuỗi.Split cho một giải pháp chung, bởi vì bạn sẽ sử dụng nhiều bộ nhớ hơn ở mọi nơi bạn sử dụng chức năng - chuỗi gốc và bản sao tách, cả trong bộ nhớ. Hãy tin tôi rằng đây có thể là một vấn đề nghiêm trọng khi bạn bắt đầu mở rộng quy mô - chạy ứng dụng xử lý hàng loạt 32 bit xử lý các tài liệu 100MB và bạn sẽ giải quyết được tám luồng đồng thời. Không phải là tôi đã từng đến đó trước đây ...
Thay vào đó, sử dụng một trình vòng lặp như thế này;
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;
}
}
}
Điều này sẽ cho phép bạn thực hiện một vòng lặp hiệu quả hơn về bộ nhớ xung quanh dữ liệu của bạn;
foreach(var line in document.SplitToLines())
{
// one line at a time...
}
Tất nhiên, nếu bạn muốn tất cả trong bộ nhớ, bạn có thể làm điều này;
var allTheLines = document.SplitToLines.ToArray();
blah.SplitToLines..
như document.SplitToLines...
thế nào?
this
vào các tham số chính thức làm cho nó trở thành một phương thức mở rộng.
Dựa trên câu trả lời của Guffa, trong một lớp mở rộng, sử dụng:
public static string[] Lines(this string source) {
return source.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
}
Đối với một biến chuỗi s
:
s.Split(new string[]{Environment.NewLine},StringSplitOptions.None)
Điều này sử dụng định nghĩa môi trường của bạn về kết thúc dòng. Trên Windows, các kết thúc dòng là CR-LF (trả về vận chuyển, nguồn cấp dữ liệu) hoặc trong các ký tự thoát của C # \r\n
.
Đây là một giải pháp đáng tin cậy, bởi vì nếu bạn kết hợp lại các dòng với String.Join
, thì điều này bằng với chuỗi ban đầu của bạn:
var lines = s.Split(new string[]{Environment.NewLine},StringSplitOptions.None);
var reconstituted = String.Join(Environment.NewLine,lines);
Debug.Assert(s==reconstituted);
Những gì không làm:
StringSplitOptions.RemoveEmptyEntries
, bởi vì điều này sẽ phá vỡ đánh dấu, chẳng hạn như Markdown, nơi các dòng trống có mục đích cú pháp.new char[]{Environment.NewLine}
, bởi vì trên Windows, điều này sẽ tạo ra một phần tử chuỗi trống cho mỗi dòng mới.Regex cũng là một lựa chọn:
private string[] SplitStringByLineFeed(string inpString)
{
string[] locResult = Regex.Split(inpString, "[\r\n]+");
return locResult;
}
"\r?\n"
.
Tôi chỉ nghĩ rằng tôi sẽ thêm hai bit của mình, bởi vì các giải pháp khác cho câu hỏi này không thuộc phân loại mã có thể sử dụng lại và không thuận tiện.
Khối mã sau đây mở rộng string
đối tượng để nó có sẵn như một phương thức tự nhiên khi làm việc với các chuỗi.
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);
}
}
}
Bây giờ bạn có thể sử dụng .Split()
hàm từ bất kỳ chuỗi nào như sau:
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);
Để phân chia trên một ký tự dòng mới, chỉ cần vượt qua "\n"
hoặc "\r\n"
làm tham số dấu phân cách.
Nhận xét: Sẽ thật tuyệt nếu Microsoft thực hiện quá tải này.
Environment.Newline
được ưu tiên để mã hóa cứng \n
hoặc \r\n
.
Environment.Newline
dành cho khả năng tương thích đa nền tảng, không phải để làm việc với các tệp sử dụng các kết thúc dòng khác với hệ điều hành hiện tại. Xem ở đây để biết thêm thông tin , vì vậy nó thực sự phụ thuộc vào những gì nhà phát triển đang làm việc với. Việc sử dụng Environment.Newline
đảm bảo không có sự thống nhất trong loại trả về dòng giữa các hệ điều hành, trong đó 'mã hóa cứng' mang lại cho nhà phát triển toàn quyền kiểm soát.
.Newline
không phải là phép thuật, dưới mui xe, nó chỉ là các chuỗi như được cung cấp ở trên dựa trên một công tắc nếu nó đang chạy trên unix hoặc trên các cửa sổ. Đặt cược an toàn nhất, trước tiên là thực hiện thay thế một chuỗi cho tất cả "\ r \ n" và sau đó phân tách trên "\ n". Trường hợp sử dụng .Newline
không thành công, là khi bạn đang làm việc với các tệp được lưu bởi các chương trình khác sử dụng một phương pháp khác để ngắt dòng. Nó hoạt động tốt nếu bạn biết mỗi khi tệp đọc luôn sử dụng ngắt dòng của hệ điều hành hiện tại của bạn.
foo = foo.Replace("\r\n", "\n"); string[] result = foo.Split('\n');
. Tôi có hiểu chính xác rằng điều này hoạt động trên tất cả các nền tảng?
Tôi hiện đang sử dụng chức năng này (dựa trên các câu trả lời khác) trong VB.NET:
Private Shared Function SplitLines(text As String) As String()
Return text.Split({Environment.NewLine, vbCrLf, vbLf}, StringSplitOptions.None)
End Function
Nó cố gắng phân tách trên dòng mới nền tảng cục bộ trước, và sau đó rơi trở lại từng dòng mới có thể.
Tôi chỉ cần điều này trong một lớp cho đến nay. Nếu điều đó thay đổi, tôi có thể sẽ thực hiện điều này Public
và chuyển nó sang một lớp tiện ích, và thậm chí có thể biến nó thành một phương thức mở rộng.
Đây là cách tham gia các dòng sao lưu, để có biện pháp tốt:
Private Shared Function JoinLines(lines As IEnumerable(Of String)) As String
Return String.Join(Environment.NewLine, lines)
End Function
"\r"
= trả lại. "\r\n"
= trả lại + dòng mới. (vui lòng xem lại bài đăng này và giải pháp được chấp nhận tại đây
Vâng, thực sự phân chia nên làm:
//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);
Các RemoveEmptyStrings tùy chọn sẽ đảm bảo bạn không có mục rỗng do \ n sau một \ r
(Chỉnh sửa để phản ánh ý kiến :) Lưu ý rằng nó cũng sẽ loại bỏ các dòng trống chính hãng trong văn bản. Đây thường là những gì tôi muốn nhưng nó có thể không phải là yêu cầu của bạn.
Tôi không biết về Môi trường. Mới, nhưng tôi đoán đây là một giải pháp rất tốt.
Cố gắng của tôi sẽ là:
string str = "Test Me\r\nTest Me\nTest Me";
var splitted = str.Split('\n').Select(s => s.Trim()).ToArray();
.Trim bổ sung sẽ xóa mọi \ r hoặc \ n có thể vẫn còn (ví dụ: khi ở trên windows nhưng tách một chuỗi với các ký tự os x newline). Có lẽ không phải là phương pháp nhanh nhất.
BIÊN TẬP:
Như các ý kiến đã chỉ ra một cách chính xác, điều này cũng loại bỏ bất kỳ khoảng trắng nào ở đầu dòng hoặc trước nguồn cấp dữ liệu mới. Nếu bạn cần giữ khoảng trắng đó, hãy sử dụng một trong các tùy chọn khác.
Câu trả lời ngớ ngẩn: ghi vào một tập tin tạm thời để bạn có thể sử dụng đáng kính
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
, vì nó không xác định loại biến, vì vậy bạn có thể không hiểu cách sử dụng đối tượng đó hoặc đối tượng đó đại diện cho điều gì. Thêm vào đó, điều này cho thấy việc viết các dòng và thậm chí không chỉ định tên tệp, vì vậy tôi nghi ngờ nó sẽ hoạt động. Sau đó, khi đọc, đường dẫn đến tệp một lần nữa không được chỉ định. Giả sử path
là vậy C:\Temp\test.txt
, bạn nên có string[] lines = File.ReadLines(path);
.
Path.GetTempFileName
msdn.microsoft.com/en-us/l Library / Hay và nó nói rằng nó tạo ra một tệp không byte và trả về "đường dẫn đầy đủ của tệp đó". Tôi có thể thề rằng tôi đã thử điều này trước đây và nó đã đưa ra một ngoại lệ vì nó không tìm thấy một tập tin, nhưng thay vào đó được trả lại một vị trí thư mục. Tôi biết các đối số để sử dụng var
, nhưng tôi nói rằng nó KHÔNG được khuyến khích vì nó không hiển thị đối tượng biến là gì. Nó che giấu nó.
Rất dễ dàng, thực sự.
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);
}
Environment.NewLine
giống như trong VB.