Ho bisogno di dividere una stringa in newline in .NET e l'unico modo che conosco per dividere le stringhe è con il metodo Split . Tuttavia ciò non mi permetterà di dividere (facilmente) su una nuova riga, quindi qual è il modo migliore per farlo?
Ho bisogno di dividere una stringa in newline in .NET e l'unico modo che conosco per dividere le stringhe è con il metodo Split . Tuttavia ciò non mi permetterà di dividere (facilmente) su una nuova riga, quindi qual è il modo migliore per farlo?
Risposte:
Per dividere una stringa è necessario utilizzare il sovraccarico che accetta una matrice di stringhe:
string[] lines = theText.Split(
new[] { Environment.NewLine },
StringSplitOptions.None
);
Modifica:
se si desidera gestire diversi tipi di interruzioni di riga in un testo, è possibile utilizzare la possibilità di abbinare più di una stringa. Questo si dividerà correttamente su entrambi i tipi di interruzione di riga e manterrà le righe vuote e la spaziatura nel testo:
string[] lines = theText.Split(
new[] { "\r\n", "\r", "\n" },
StringSplitOptions.None
);
Environment.NewLine
proprietà contiene la nuova riga predefinita per il sistema. Per un sistema Windows, ad esempio, lo sarà "\r\n"
.
\n
lasciando una \r
alla fine di ogni riga, quindi emette le linee \r\n
tra loro.
\r
e \n
escape (tra gli altri) hanno un significato speciale per il compilatore C #. VB non ha quelle sequenze di escape, quindi lì vengono usate quelle costanti.
Che ne dici di usare un StringReader
?
using (System.IO.StringReader reader = new System.IO.StringReader(input)) {
string line = reader.ReadLine();
}
while
ciclo che dovrebbe essere aggiunto a questa risposta.
Dovresti essere in grado di dividere la stringa abbastanza facilmente, in questo modo:
aString.Split(Environment.NewLine.ToCharArray());
Cerca di evitare l'uso della stringa. Spaccati per una soluzione generale, perché utilizzerai più memoria ovunque usi la funzione: la stringa originale e la copia divisa, entrambe in memoria. Fidati di me che questo può essere un grosso problema quando inizi a ridimensionare: esegui un'app di elaborazione batch a 32 bit che elabora documenti da 100 MB e ti ritroverai con otto thread simultanei. Non che ci sia stato prima ...
Invece, usa un iteratore come questo;
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;
}
}
}
Ciò ti consentirà di eseguire un ciclo più efficiente della memoria attorno ai tuoi dati;
foreach(var line in document.SplitToLines())
{
// one line at a time...
}
Certo, se vuoi tutto in memoria, puoi farlo;
var allTheLines = document.SplitToLines.ToArray();
blah.SplitToLines..
ad esempio document.SplitToLines...
?
this
i parametri formali rendendolo un metodo di estensione.
Sulla base della risposta di Guffa, in una classe di estensione, utilizzare:
public static string[] Lines(this string source) {
return source.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
}
Per una variabile stringa s
:
s.Split(new string[]{Environment.NewLine},StringSplitOptions.None)
Questo utilizza la definizione del tuo ambiente di terminazioni di linea. Su Windows, i finali di riga sono CR-LF (ritorno a capo, avanzamento riga) o in caratteri di escape di C # \r\n
.
Questa è una soluzione affidabile, perché se ricombini le linee con String.Join
, questo equivale alla tua stringa originale:
var lines = s.Split(new string[]{Environment.NewLine},StringSplitOptions.None);
var reconstituted = String.Join(Environment.NewLine,lines);
Debug.Assert(s==reconstituted);
Cosa non fare:
StringSplitOptions.RemoveEmptyEntries
, perché ciò interromperà il markup come Markdown in cui le righe vuote hanno uno scopo sintattico.new char[]{Environment.NewLine}
, perché su Windows questo creerà un elemento stringa vuoto per ogni nuova riga.Regex è anche un'opzione:
private string[] SplitStringByLineFeed(string inpString)
{
string[] locResult = Regex.Split(inpString, "[\r\n]+");
return locResult;
}
"\r?\n"
.
Ho solo pensato di aggiungere i miei due bit, perché le altre soluzioni su questa domanda non rientrano nella classificazione riutilizzabile del codice e non sono convenienti.
Il seguente blocco di codice estende l' string
oggetto in modo che sia disponibile come metodo naturale quando si lavora con le stringhe.
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);
}
}
}
Ora puoi usare la .Split()
funzione da qualsiasi stringa come segue:
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);
Per dividere un carattere di nuova riga, è sufficiente passare "\n"
o "\r\n"
come parametro delimitatore.
Commento: Sarebbe bello se Microsoft implementasse questo sovraccarico.
Environment.Newline
è preferito alla codifica hardware \n
o \r\n
.
Environment.Newline
serve per la compatibilità multipiattaforma, non per lavorare con file che usano terminazioni di linea diverse rispetto all'attuale sistema operativo. Vedi qui per maggiori informazioni , quindi dipende davvero da cosa sta lavorando lo sviluppatore. L'uso di Environment.Newline
garantisce che non vi sia coerenza nel tipo di ritorno di riga tra i sistemi operativi, in cui la "codifica rigida" offre allo sviluppatore il pieno controllo.
.Newline
non è magico, sotto il cofano sono solo le stringhe fornite sopra basate su un interruttore di se è in esecuzione su Unix o su Windows. La scommessa più sicura, è prima fare una sostituzione di stringa per tutto "\ r \ n" e poi dividere su "\ n". Dove l'utilizzo .Newline
non riesce, è quando si lavora con file salvati da altri programmi che utilizzano un metodo diverso per le interruzioni di riga. Funziona bene se lo sai ogni volta che il file letto utilizza sempre le interruzioni di riga del tuo attuale sistema operativo.
foo = foo.Replace("\r\n", "\n"); string[] result = foo.Split('\n');
. Comprendo correttamente che funziona su tutte le piattaforme?
Attualmente sto usando questa funzione (sulla base di altre risposte) in VB.NET:
Private Shared Function SplitLines(text As String) As String()
Return text.Split({Environment.NewLine, vbCrLf, vbLf}, StringSplitOptions.None)
End Function
Tenta di dividere prima la nuova riga locale-piattaforma, quindi ricade su ciascuna possibile nuova riga.
Finora ne ho avuto bisogno solo all'interno di una classe. Se ciò cambia, probabilmente lo farò Public
e lo sposterò in una classe di utilità, e forse lo trasformerò anche in un metodo di estensione.
Ecco come unire le linee di backup, per una buona misura:
Private Shared Function JoinLines(lines As IEnumerable(Of String)) As String
Return String.Join(Environment.NewLine, lines)
End Function
"\r"
= ritorno. "\r\n"
= return + nuova riga. (rivedi questo post e la soluzione accettata qui
Bene, in realtà la divisione dovrebbe fare:
//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);
L' opzione RemoveEmptyStrings farà in modo di non avere voci vuote a causa di \ n che segue a \ r
(Modifica per riflettere i commenti :) Nota che eliminerà anche le righe vuote autentiche nel testo. Questo è di solito quello che voglio ma potrebbe non essere il tuo requisito.
Non sapevo di Environment.Newline, ma credo che questa sia un'ottima soluzione.
Il mio tentativo sarebbe stato:
string str = "Test Me\r\nTest Me\nTest Me";
var splitted = str.Split('\n').Select(s => s.Trim()).ToArray();
Il .Trim aggiuntivo rimuove qualsiasi \ r o \ n che potrebbe essere ancora presente (ad es. Su windows ma suddividendo una stringa con caratteri os x newline). Probabilmente non è il metodo più veloce però.
MODIFICARE:
Come sottolineato correttamente dai commenti, questo rimuove anche qualsiasi spazio bianco all'inizio della riga o prima del nuovo feed di riga. Se è necessario preservare quello spazio bianco, utilizzare una delle altre opzioni.
Risposta sciocca: scrivi in un file temporaneo in modo da poter usare il venerabile
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
, poiché non definisce il tipo di variabile, quindi potresti non capire come usare quell'oggetto o cosa rappresenta quell'oggetto. Inoltre, questo mostra la scrittura delle righe e non specifica nemmeno un nome di file, quindi dubito che funzionerebbe. Quindi, durante la lettura, il percorso del file non viene nuovamente specificato. Supponendo che path
sia C:\Temp\test.txt
, dovresti avere string[] lines = File.ReadLines(path);
.
Path.GetTempFileName
msdn.microsoft.com/en-us/library/… e dice che crea un file a zero byte e restituisce "il percorso completo di quel file". Potrei giurare di averlo provato prima e ha dato un'eccezione perché non ha trovato un file, ma è stato invece restituito un percorso di cartella. Conosco gli argomenti da usare var
, ma direi che NON è raccomandato perché non mostra quale sia l'oggetto variabile. Lo offusca.
Molto semplice, in realtà.
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
proprio come in VB.