C #: Loop através de linhas de string multilinha

100

Qual é uma boa maneira de percorrer cada linha de uma string multilinha sem usar muito mais memória (por exemplo, sem dividi-la em uma matriz)?

flamejante
fonte

Respostas:

158

Sugiro usar uma combinação de StringReadere minha LineReaderclasse, que faz parte do MiscUtil, mas também está disponível nesta resposta do StackOverflow - você pode copiar facilmente apenas essa classe em seu próprio projeto de utilitário. Você o usaria assim:

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

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

Looping sobre todas as linhas em um corpo de dados de cadeia (se isso é um arquivo ou qualquer outro) é tão comum que não deve exigir o código de chamada a ser teste para NULL etc :) Dito isto, se você não quer fazer um loop manual, esta é a forma que normalmente prefiro em vez de Fredrik:

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

Dessa forma, você só precisa testar a nulidade uma vez e não precisa pensar em um loop do / while (que, por algum motivo, sempre exige mais esforço para ler do que um loop while direto).

Jon Skeet
fonte
74

Você pode usar um StringReaderpara ler uma linha de cada 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
fonte
1
Ótimo; +1; isso ajudou; mas quero apenas acrescentar que não é necessário usar o bloco "usando" porque não há recursos para fechar neste caso. Veja os comentários no artigo StringReader em docs.microsoft.com
RD Alkire
10

Eu sei que isso foi respondido, mas gostaria de adicionar minha própria resposta:

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

do 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
fonte
2

Aqui está um snippet de código rápido que encontrará a primeira linha não vazia em uma string:

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
fonte
2

Para atualizar esta questão antiga para .NET 4, agora existe uma maneira muito mais simples:

var lines = File.ReadAllLines(filename);

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

Tente usar o método String.Split:

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

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