Ben .NET'te yeni satırlara bir dize bölmek ve dizeleri bölmek için bildiğim tek yolu Split yöntemidir. Ancak bu, yeni bir satıra (kolayca) ayrılmama izin vermeyecek, bunu yapmanın en iyi yolu nedir?
Ben .NET'te yeni satırlara bir dize bölmek ve dizeleri bölmek için bildiğim tek yolu Split yöntemidir. Ancak bu, yeni bir satıra (kolayca) ayrılmama izin vermeyecek, bunu yapmanın en iyi yolu nedir?
Yanıtlar:
Bir dizeyi bölmek için bir dizi dizeyi alan aşırı yükü kullanmanız gerekir:
string[] lines = theText.Split(
new[] { Environment.NewLine },
StringSplitOptions.None
);
Düzenleme:
Bir metinde farklı satır sonları işlemek istiyorsanız, birden fazla dizeyi eşleme yeteneğini kullanabilirsiniz. Bu, her iki satır sonu türüne de doğru şekilde bölünecek ve metindeki boş satırları ve aralıkları koruyacaktır:
string[] lines = theText.Split(
new[] { "\r\n", "\r", "\n" },
StringSplitOptions.None
);
Environment.NewLine
Özellik, sistem için varsayılan yeni satırı içerir. Örneğin bir Windows sistemi için "\r\n"
.
\n
bir bırakarak ayrılması ve \r
ardından \r\n
aralarında bir ile çıktılar üretmesi olacaktır .
\r
ve \n
diğerleri arasında) ve kaçış dizilerinin C # derleyicisi için özel bir anlamı vardır. VB'de bu kaçış dizileri yoktur, bu nedenle bu sabitler kullanılır.
A kullanmaya ne dersiniz StringReader
?
using (System.IO.StringReader reader = new System.IO.StringReader(input)) {
string line = reader.ReadLine();
}
while
.
Dizenizi oldukça kolayca bölebilmelisiniz, şöyle:
aString.Split(Environment.NewLine.ToCharArray());
Genel bir çözüm için string.Split kullanmaktan kaçının, çünkü işlevi kullandığınız her yerde daha fazla bellek kullanırsınız - orijinal dize ve bölünmüş kopya, her ikisi de bellekte. Güvenmeye çalışın, ölçeklendirmeye başladığınızda bir sorun cehennemi olabilir - 100 MB'lık belgeleri işleyen 32 bit toplu işleme uygulaması çalıştırın ve eşzamanlı sekiz iş parçacığına bürüneceksiniz. Daha önce orada bulunduğumdan değil ...
Bunun yerine, böyle bir yineleyici kullanın;
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;
}
}
}
Bu, verileriniz çevresinde daha verimli bir bellek döngüsü gerçekleştirmenizi sağlar;
foreach(var line in document.SplitToLines())
{
// one line at a time...
}
Tabii ki, eğer hepsini hafızada istiyorsanız, bunu yapabilirsiniz;
var allTheLines = document.SplitToLines.ToArray();
blah.SplitToLines..
örn document.SplitToLines...
.
this
, onu bir genişletme yöntemi haline getiren resmi parametreleri koyuyorsunuz .
Guffa'nın cevabına göre, bir uzantı sınıfında şunları kullanın:
public static string[] Lines(this string source) {
return source.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
}
Bir dize değişkeni için s
:
s.Split(new string[]{Environment.NewLine},StringSplitOptions.None)
Bu, ortamınızın satır sonları tanımını kullanır. Windows'ta satır sonları CR-LF (satır başı, satır besleme) veya C # 'ın çıkış karakteridir \r\n
.
Bu güvenilir bir çözümdür, çünkü çizgileri yeniden birleştirirseniz String.Join
, bu orijinal dizenize eşittir:
var lines = s.Split(new string[]{Environment.NewLine},StringSplitOptions.None);
var reconstituted = String.Join(Environment.NewLine,lines);
Debug.Assert(s==reconstituted);
Ne yapmamalı:
StringSplitOptions.RemoveEmptyEntries
, çünkü bu boş satırların sözdizimsel amaçlara sahip olduğu Markdown gibi işaretlemeyi kıracaktır.new char[]{Environment.NewLine}
, çünkü Windows'ta bu her yeni satır için bir boş dize öğesi oluşturacaktır.Normal ifade de bir seçenektir:
private string[] SplitStringByLineFeed(string inpString)
{
string[] locResult = Regex.Split(inpString, "[\r\n]+");
return locResult;
}
"\r?\n"
.
Sadece iki bitimi ekleyeceğimi düşündüm, çünkü bu sorudaki diğer çözümler yeniden kullanılabilir kod sınıflandırmasına girmiyor ve uygun değil.
Aşağıdaki kod bloğu string
nesneyi, dizelerle çalışırken doğal bir yöntem olarak kullanılabilecek şekilde genişletir .
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);
}
}
}
Artık .Split()
işlevi herhangi bir dizeden aşağıdaki gibi kullanabilirsiniz :
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);
Bir yeni satır karakterine bölünmek için, "\n"
ya "\r\n"
da ayırıcı parametresi olarak geçmeniz yeterlidir .
Yorum: Microsoft'un bu aşırı yüklemeyi uygulaması iyi olurdu.
Environment.Newline
sert kodlamaya ya \n
da tercih edilir \r\n
.
Environment.Newline
platformlar arası uyumluluk içindir, geçerli işletim sisteminden farklı satır sonlandırmaları kullanan dosyalarla çalışmak için değildir. Daha fazla bilgi için buraya bakın , bu yüzden geliştiricinin neyle çalıştığına bağlı. 'İn kullanımı, Environment.Newline
' sabit kodlamanın 'geliştiriciye tam denetim sağladığı işletim sistemleri arasında satır dönüş türünde tutarlılık olmamasını sağlar.
.Newline
sihir değil, kaputun altında sadece unix üzerinde mi yoksa pencerelerde mi çalıştığının bir anahtarına dayanarak yukarıda verilen dizeler. En güvenli bahis, önce tüm "\ r \ n" için bir dize değiştirme yapmak ve sonra "\ n" üzerine bölmektir. Kullanarak Nerede .Newline
başarısız satır sonları için farklı bir yöntem kullanan diğer programlar tarafından kaydedilen dosyaları ile çalışırken vardır. Dosyanın her zaman geçerli işletim sisteminizin satır sonlarını kullandığını biliyorsanız iyi çalışır.
foo = foo.Replace("\r\n", "\n"); string[] result = foo.Split('\n');
. Bunun tüm platformlarda çalıştığını doğru anlıyor muyum?
Şu anda VB.NET bu işlevi (diğer yanıtlara dayalı) kullanıyorum:
Private Shared Function SplitLines(text As String) As String()
Return text.Split({Environment.NewLine, vbCrLf, vbLf}, StringSplitOptions.None)
End Function
Önce platform-yerel satırsonuna bölünmeye çalışır ve sonra olası her satırsonuna geri döner.
Buna şimdiye kadar sadece bir sınıfta ihtiyacım vardı. Bu değişirse, muhtemelen bunu yapacağım Public
ve bir yardımcı program sınıfına taşıyacağım ve hatta bir uzantı yöntemi bile yapacağım.
İyi bir önlem için hatlara nasıl katılacağınız aşağıda açıklanmıştır:
Private Shared Function JoinLines(lines As IEnumerable(Of String)) As String
Return String.Join(Environment.NewLine, lines)
End Function
"\r"
= dönüş. "\r\n"
= dönüş + yeni satır. (Lütfen bu
Aslında bölünmüş yapmalı:
//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 seçenek, bir \ r aşağıdaki dolayı \ n boş girdileri yok emin olun
(Yorumları yansıtacak şekilde düzenleyin :) Metin içindeki orijinal boş satırları da sileceğini unutmayın. Bu genellikle istediğim şeydir, ancak gereksiniminiz olmayabilir.
Çevreyi bilmiyordum.Yeni, ama sanırım bu çok iyi bir çözüm.
Benim denemem şöyle olurdu:
string str = "Test Me\r\nTest Me\nTest Me";
var splitted = str.Split('\n').Select(s => s.Trim()).ToArray();
Ek .Trim, hala mevcut olabilecek herhangi bir \ r veya \ n öğesini kaldırır (örneğin, pencerelerde iken, os x newline karakterleriyle bir dizeyi bölerek). Muhtemelen en hızlı yöntem olmasa da.
DÜZENLE:
Yorumların doğru bir şekilde işaret ettiği gibi, satırın başlangıcında veya yeni satır beslemesinden önceki boşlukları da kaldırır. Bu boşluğu korumanız gerekiyorsa, diğer seçeneklerden birini kullanın.
Aptalca cevap: geçici bir dosyaya yazmak böylece saygıdeğer kullanabilirsiniz
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
Değişken türünü tanımlamadığından kaçının , bu nedenle o nesneyi nasıl kullanacağınızı veya o nesnenin neyi temsil ettiğini anlamayabilirsiniz. Artı, bu satırları yazma gösterir ve bir dosya adı bile belirtmez, bu yüzden işe yarayacağından şüpheliyim. Daha sonra, okurken, dosyanın yolu tekrar belirtilmez. Varsayarsak path
ise C:\Temp\test.txt
, o zaman olmalıdır string[] lines = File.ReadLines(path);
.
Path.GetTempFileName
msdn.microsoft.com/en-us/library/… ' ı aradım ve sıfır baytlık bir dosya oluşturduğunu ve "bu dosyanın tam yolunu" döndürdüğünü söylüyor . Yemin edebilirim daha önce denedim ve bir dosya bulamadığı için bir istisna verdi, ancak bunun yerine bir klasör konumu döndürüldü. Ben kullanmak için argüman biliyorum var
, ama değişken nesnenin ne olduğunu göstermez çünkü tavsiye DEĞİL söyleyebilirim. O şaşırtıyor.
Aslında çok kolay.
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
tıpkı VB'deki gibi.