C #: recorrer líneas de cadena de varias líneas

100

¿Cuál es una buena manera de recorrer cada línea de una cadena de varias líneas sin usar mucha más memoria (por ejemplo, sin dividirla en una matriz)?

flameante
fuente

Respuestas:

158

Sugiero usar una combinación de StringReadery mi LineReaderclase, que es parte de MiscUtil pero también está disponible en esta respuesta de StackOverflow : puede copiar fácilmente solo esa clase en su propio proyecto de utilidad. Lo usarías así:

string text = @"First line
second line
third line";

foreach (string line in new LineReader(() => new StringReader(text)))
{
    Console.WriteLine(line);
}

Bucle sobre todas las líneas de un conjunto de datos de cadena (ya sea un archivo o lo que sea) es tan común que no debería requerir el código de llamada a ser nula para probar etc :) Dicho esto, si usted no quiere hacer una bucle manual, esta es la forma que normalmente prefiero a la de Fredrik:

using (StringReader reader = new StringReader(input))
{
    string line;
    while ((line = reader.ReadLine()) != null)
    {
        // Do something with the line
    }
}

De esta manera, solo tiene que probar la nulidad una vez, y tampoco tiene que pensar en un bucle do / while (que por alguna razón siempre me cuesta más leer que un bucle while directo).

Jon Skeet
fuente
74

Puede usar a StringReaderpara leer una línea a la vez:

using (StringReader reader = new StringReader(input))
{
    string line = string.Empty;
    do
    {
        line = reader.ReadLine();
        if (line != null)
        {
            // do something with the line
        }

    } while (line != null);
}
Fredrik Mörk
fuente
1
Excelente; +1; esto ayudó; pero solo quiero agregar que uno no necesita usar el bloque "using" porque no hay recursos para cerrar en este caso. Consulte los comentarios en el artículo de StringReader en docs.microsoft.com
RD Alkire
10

Sé que esto ha sido respondido, pero me gustaría agregar mi propia respuesta:

using (var reader = new StringReader(multiLineString))
{
    for (string line = reader.ReadLine(); line != null; line = reader.ReadLine())
    {
        // Do something with the line
    }
}
Niels
fuente
7

de MSDN para StringReader

    string textReaderText = "TextReader is the abstract base " +
        "class of StreamReader and StringReader, which read " +
        "characters from streams and strings, respectively.\n\n" +

        "Create an instance of TextReader to open a text file " +
        "for reading a specified range of characters, or to " +
        "create a reader based on an existing stream.\n\n" +

        "You can also use an instance of TextReader to read " +
        "text from a custom backing store using the same " +
        "APIs you would use for a string or a stream.\n\n";

    Console.WriteLine("Original text:\n\n{0}", textReaderText);

    // From textReaderText, create a continuous paragraph 
    // with two spaces between each sentence.
    string aLine, aParagraph = null;
    StringReader strReader = new StringReader(textReaderText);
    while(true)
    {
        aLine = strReader.ReadLine();
        if(aLine != null)
        {
            aParagraph = aParagraph + aLine + " ";
        }
        else
        {
            aParagraph = aParagraph + "\n";
            break;
        }
    }
    Console.WriteLine("Modified text:\n\n{0}", aParagraph);
tster
fuente
2

Aquí hay un fragmento de código rápido que encontrará la primera línea no vacía en una cadena:

string line1;
while (
    ((line1 = sr.ReadLine()) != null) &&
    ((line1 = line1.Trim()).Length == 0)
)
{ /* Do nothing - just trying to find first non-empty line*/ }

if(line1 == null){ /* Error - no non-empty lines in string */ }
palswim
fuente
2

Para actualizar esta antigua pregunta para .NET 4, ahora hay una forma mucho más ordenada:

var lines = File.ReadAllLines(filename);

foreach (string line in lines)
{
    Console.WriteLine(line);
}
NickG
fuente
0

Intente usar el método String.Split:

string text = @"First line
second line
third line";

foreach (string line in text.Split('\n'))
{
    // do something
}
emmediemme82
fuente