Necesito dividir una cadena en nuevas líneas en .NET y la única forma en que sé dividir cadenas es con el método Split . Sin embargo, eso no me permitirá dividir (fácilmente) en una nueva línea, entonces, ¿cuál es la mejor manera de hacerlo?
Necesito dividir una cadena en nuevas líneas en .NET y la única forma en que sé dividir cadenas es con el método Split . Sin embargo, eso no me permitirá dividir (fácilmente) en una nueva línea, entonces, ¿cuál es la mejor manera de hacerlo?
Respuestas:
Para dividir en una cadena, debe usar la sobrecarga que toma una matriz de cadenas:
string[] lines = theText.Split(
new[] { Environment.NewLine },
StringSplitOptions.None
);
Editar:
si desea manejar diferentes tipos de saltos de línea en un texto, puede usar la capacidad de hacer coincidir más de una cadena. Esto se dividirá correctamente en cualquier tipo de salto de línea y conservará las líneas vacías y el espaciado en el texto:
string[] lines = theText.Split(
new[] { "\r\n", "\r", "\n" },
StringSplitOptions.None
);
Environment.NewLine
propiedad contiene la nueva línea predeterminada para el sistema. Para un sistema Windows, por ejemplo, lo será "\r\n"
.
\n
dejar un \r
al final de cada línea, y luego genera las líneas con un \r\n
entre ellos.
\r
y \n
(entre otras) tienen un significado especial para el compilador de C #. VB no tiene esas secuencias de escape, por lo que se utilizan esas constantes en su lugar.
¿Qué hay de usar un StringReader
?
using (System.IO.StringReader reader = new System.IO.StringReader(input)) {
string line = reader.ReadLine();
}
while
ciclo que debe agregarse a esta respuesta.
Debería poder dividir su cadena con bastante facilidad, así:
aString.Split(Environment.NewLine.ToCharArray());
Intente evitar usar string.Split para obtener una solución general, porque usará más memoria en todos los lugares donde use la función: la cadena original y la copia dividida, ambas en la memoria. Confía en mí que esto puede ser un gran problema cuando comienzas a escalar: ejecuta una aplicación de procesamiento por lotes de 32 bits que procesa documentos de 100 MB y obtendrás ocho hilos simultáneos. No es que haya estado allí antes ...
En su lugar, use un iterador como este;
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;
}
}
}
Esto le permitirá hacer un ciclo de memoria más eficiente alrededor de sus datos;
foreach(var line in document.SplitToLines())
{
// one line at a time...
}
Por supuesto, si lo quieres todo en la memoria, puedes hacerlo;
var allTheLines = document.SplitToLines.ToArray();
blah.SplitToLines..
por ejemplo document.SplitToLines...
?
this
los parámetros formales convirtiéndolo en un método de extensión.
Según la respuesta de Guffa, en una clase de extensión, use:
public static string[] Lines(this string source) {
return source.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
}
Para una variable de cadena s
:
s.Split(new string[]{Environment.NewLine},StringSplitOptions.None)
Esto utiliza la definición de su entorno de terminaciones de línea. En Windows, las terminaciones de línea son CR-LF (retorno de carro, avance de línea) o en los caracteres de escape de C # \r\n
.
Esta es una solución confiable, porque si recombinas las líneas con String.Join
, esto es igual a tu cadena original:
var lines = s.Split(new string[]{Environment.NewLine},StringSplitOptions.None);
var reconstituted = String.Join(Environment.NewLine,lines);
Debug.Assert(s==reconstituted);
Qué no hacer:
StringSplitOptions.RemoveEmptyEntries
, porque esto romperá el marcado, como Markdown, donde las líneas vacías tienen un propósito sintáctico.new char[]{Environment.NewLine}
, porque en Windows esto creará un elemento de cadena vacío para cada nueva línea.Regex también es una opción:
private string[] SplitStringByLineFeed(string inpString)
{
string[] locResult = Regex.Split(inpString, "[\r\n]+");
return locResult;
}
"\r?\n"
.
Solo pensé que agregaría mis dos bits, porque las otras soluciones en esta pregunta no entran en la clasificación de código reutilizable y no son convenientes.
El siguiente bloque de código extiende el string
objeto para que esté disponible como método natural cuando se trabaja con cadenas.
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);
}
}
}
Ahora puede usar la .Split()
función desde cualquier cadena de la siguiente manera:
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);
Para dividir en un carácter de nueva línea, simplemente pase "\n"
o "\r\n"
como el parámetro delimitador.
Comentario: Sería bueno si Microsoft implementara esta sobrecarga.
Environment.Newline
se prefiere a la codificación rígida \n
o \r\n
.
Environment.Newline
es para compatibilidad multiplataforma, no para trabajar con archivos que utilizan diferentes terminaciones de línea que el sistema operativo actual. Consulte aquí para obtener más información , por lo que realmente depende de con qué esté trabajando el desarrollador. El uso de Environment.Newline
asegura que no haya consistencia en el tipo de retorno de línea entre los sistemas operativos, donde la 'codificación rígida' le da al desarrollador un control total.
.Newline
no es mágico, debajo del capó son solo las cuerdas según lo dispuesto anteriormente en función de un interruptor de si se está ejecutando en Unix o en Windows. La apuesta más segura es hacer primero un reemplazo de cadena para todos "\ r \ n" y luego dividir en "\ n". Cuando el uso .Newline
falla, es cuando está trabajando con archivos guardados por otros programas que utilizan un método diferente para los saltos de línea. Funciona bien si sabe cada vez que la lectura del archivo siempre usa los saltos de línea de su sistema operativo actual.
foo = foo.Replace("\r\n", "\n"); string[] result = foo.Split('\n');
. ¿Entiendo correctamente que esto funciona en todas las plataformas?
Actualmente estoy usando esta función (basada en otras respuestas) en VB.NET:
Private Shared Function SplitLines(text As String) As String()
Return text.Split({Environment.NewLine, vbCrLf, vbLf}, StringSplitOptions.None)
End Function
Primero intenta dividirse en la nueva línea local de plataforma y luego recurre a cada nueva línea posible.
Solo he necesitado esto dentro de una clase hasta ahora. Si eso cambia, probablemente haré estoPublic
y lo moveré a una clase de utilidad, y tal vez incluso lo convierta en un método de extensión.
Aquí le mostramos cómo volver a unir las líneas, por si acaso:
Private Shared Function JoinLines(lines As IEnumerable(Of String)) As String
Return String.Join(Environment.NewLine, lines)
End Function
"\r"
= volver. "\r\n"
= retorno + nueva línea. (revise esta publicación y la solución aceptada aquí
Bueno, en realidad dividir debería hacer:
//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);
La opción RemoveEmptyStrings se asegurará de que no tenga entradas vacías debido a \ n después de un \ r
(Editar para reflejar los comentarios :) Tenga en cuenta que también descartará líneas vacías genuinas en el texto. Esto suele ser lo que quiero, pero puede que no sea su requisito.
No sabía sobre Medio Ambiente. Nueva línea, pero supongo que esta es una muy buena solución.
Mi intento hubiera sido:
string str = "Test Me\r\nTest Me\nTest Me";
var splitted = str.Split('\n').Select(s => s.Trim()).ToArray();
El .Trim adicional elimina cualquier \ r o \ n que aún pueda estar presente (por ejemplo, en Windows pero dividiendo una cadena con caracteres os x nueva línea). Sin embargo, probablemente no sea el método más rápido.
EDITAR:
Como los comentarios señalaron correctamente, esto también elimina cualquier espacio en blanco al comienzo de la línea o antes del nuevo avance de línea. Si necesita preservar ese espacio en blanco, use una de las otras opciones.
Respuesta tonta: escribe en un archivo temporal para que puedas usar el venerable
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
, ya que no define el tipo de variable, por lo que es posible que no entienda cómo usar ese objeto o qué representa ese objeto. Además, esto muestra escribir las líneas y ni siquiera especifica un nombre de archivo, por lo que dudo que funcione. Luego, al leer, la ruta al archivo nuevamente no se especifica. Suponiendo que path
sea así C:\Temp\test.txt
, entonces debería haberlo hecho string[] lines = File.ReadLines(path);
.
Path.GetTempFileName
msdn.microsoft.com/en-us/library/… y dice que crea un archivo de cero bytes y devuelve "la ruta completa de ese archivo". Podría jurar que probé esto antes y me dio una excepción porque no encontró un archivo, sino que me devolvió una ubicación de carpeta. Conozco los argumentos para usar var
, pero diría que NO se recomienda porque no muestra cuál es el objeto variable. Lo ofusca.
Muy fácil, en realidad.
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
como en VB.