Pergunta

Existe uma maneira fácil de determinar programaticamente o número de linhas dentro de um arquivo de texto?

Foi útil?

Solução

editar Sério tardia: Se você estiver usando .NET 4.0 ou posterior

A classe File tem um novo href="http://msdn.microsoft.com/en-us/library/dd383503.aspx" rel="noreferrer"> ReadLines método que preguiçosamente enumera linhas em vez de avidamente lê-los todos em uma matriz como ReadAllLines. Então, agora você pode ter tanto a eficiência e concisão com:

var lineCount = File.ReadLines(@"C:\file.txt").Count();

Resposta Original

Se você não está muito preocupado com eficiência, você pode simplesmente escrever:

var lineCount = File.ReadAllLines(@"C:\file.txt").Length;

Para um método mais eficiente que você poderia fazer:

var lineCount = 0;
using (var reader = File.OpenText(@"C:\file.txt"))
{
    while (reader.ReadLine() != null)
    {
        lineCount++;
    }
}

Editar: Em resposta a perguntas sobre a eficiência

A razão que eu disse que o segundo foi mais eficiente foi sobre o uso de memória, não necessariamente velocidade. O primeiro carrega todo o conteúdo do arquivo em uma matriz que significa que deve alocar pelo menos tanta memória quanto o tamanho do arquivo. A segunda simplesmente loops de uma linha de cada vez para que ele nunca tem que alocar o valor do mais de uma linha de memória de cada vez. Esta não é tão importante para arquivos pequenos, mas para arquivos maiores que poderia ser um problema (se você tentar e encontrar o número de linhas em um arquivo de 4 GB em um sistema de 32 bits, por exemplo, onde há simplesmente não é suficiente espaço de endereço do modo de usuário para alocar uma matriz deste grande).

Em termos de velocidade eu não esperar que haja um monte nele. É possível que ReadAllLines tem algumas otimizações internas, mas por outro lado ele pode ter que alocar um pedaço enorme de memória. Eu acho que ReadAllLines pode ser mais rápido para arquivos pequenos, mas significativamente mais lenta para arquivos grandes; que a única maneira de dizer seria para medi-la com um profiler Cronômetro ou código.

Outras dicas

O mais fácil:

int lines = File.ReadAllLines("myfile").Length;

Este seria usar menos memória, mas, provavelmente, demorar mais tempo

int count = 0;
string line;
TextReader reader = new StreamReader("file.txt");
while ((line = reader.ReadLine()) != null)
{
  count++;
}
reader.Close();

Se por fácil dizer algumas linhas de código que são fáceis de decifrar, mas por acaso ineficiente?

string[] lines = System.IO.File.RealAllLines($filename);
int cnt = lines.Count();

Isso é provavelmente a maneira mais rápida de saber quantas linhas.

Você também pode fazer (dependendo se você está tamponamento-lo em)

#for large files
while (...reads into buffer){
string[] lines = Regex.Split(buffer,System.Enviorment.NewLine);
}

Existem outras inúmeras maneiras, mas uma das opções acima é provavelmente o que você vai ir com ele.

Você poderia rapidamente lê-lo, e incrementar um contador, basta usar um loop para incremento, não fazer nada com o texto.

contar os feeds retornos de carro / linha. Eu acredito em unicode eles ainda são 0x000D e 0x000A respectivamente. Dessa forma, você pode ser tão eficiente ou ineficiente como você quer, e decidir se você tem que lidar com ambos os personagens ou não

A opção viável, e um que eu usei pessoalmente, seria para adicionar seu próprio cabeçalho para a primeira linha do arquivo. Eu fiz isso por um formato de modelo personalizado para o meu jogo. Basicamente, eu tenho uma ferramenta que otimiza meus obj arquivos, se livrar da porcaria que eu não preciso, converte-los para um melhor layout, e, em seguida, escreve o número total de linhas, rostos, normais, vértices, e UVs textura em a primeira linha. Esses dados são, em seguida, utilizado por vários tampões de matriz quando o modelo é carregado.

Isso também é útil porque você só precisa percorrer o arquivo de uma vez para carregá-lo em, em vez de uma vez para contar as linhas, e novamente para ler os dados em seus buffers criados.

A leitura de um arquivo em e por si só leva algum tempo, coleta de lixo, o resultado é um outro problema, enquanto você lê o arquivo inteiro apenas para contar o caractere (s) nova linha,

Em algum momento, alguém vai ter que ler os caracteres no arquivo, independentemente se este quadro ou se é o seu código. Isto significa que você tem que abrir o arquivo e lê-lo na memória se o arquivo é grande é que isto vai ser potencialmente um problema como a memória precisa ser lixo coletado.

Nima Ara fez uma análise agradável que você pode levar em consideração

Aqui está a solução proposta, como se lê 4 caracteres de cada vez, conta o carácter de avanço de linha e re-usa o mesmo endereço de memória novamente para a próxima comparação personagem.

private const char CR = '\r';  
private const char LF = '\n';  
private const char NULL = (char)0;

public static long CountLinesMaybe(Stream stream)  
{
    Ensure.NotNull(stream, nameof(stream));

    var lineCount = 0L;

    var byteBuffer = new byte[1024 * 1024];
    const int BytesAtTheTime = 4;
    var detectedEOL = NULL;
    var currentChar = NULL;

    int bytesRead;
    while ((bytesRead = stream.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
    {
        var i = 0;
        for (; i <= bytesRead - BytesAtTheTime; i += BytesAtTheTime)
        {
            currentChar = (char)byteBuffer[i];

            if (detectedEOL != NULL)
            {
                if (currentChar == detectedEOL) { lineCount++; }

                currentChar = (char)byteBuffer[i + 1];
                if (currentChar == detectedEOL) { lineCount++; }

                currentChar = (char)byteBuffer[i + 2];
                if (currentChar == detectedEOL) { lineCount++; }

                currentChar = (char)byteBuffer[i + 3];
                if (currentChar == detectedEOL) { lineCount++; }
            }
            else
            {
                if (currentChar == LF || currentChar == CR)
                {
                    detectedEOL = currentChar;
                    lineCount++;
                }
                i -= BytesAtTheTime - 1;
            }
        }

        for (; i < bytesRead; i++)
        {
            currentChar = (char)byteBuffer[i];

            if (detectedEOL != NULL)
            {
                if (currentChar == detectedEOL) { lineCount++; }
            }
            else
            {
                if (currentChar == LF || currentChar == CR)
                {
                    detectedEOL = currentChar;
                    lineCount++;
                }
            }
        }
    }

    if (currentChar != LF && currentChar != CR && currentChar != NULL)
    {
        lineCount++;
    }
    return lineCount;
}

Acima você pode ver que uma linha é lido um carácter de cada vez também pela estrutura subjacente que você precisa ler todos os caracteres para ver o avanço de linha.

Se você perfil-la como concluída baía Nima você veria que esta é uma forma bastante rápida e eficiente de fazer isso.

try {
    string path = args[0];
    FileStream fh = new FileStream(path, FileMode.Open, FileAccess.Read);
    int i;
    string s = "";
    while ((i = fh.ReadByte()) != -1)
        s = s + (char)i;

    //its for reading number of paragraphs
    int count = 0;
    for (int j = 0; j < s.Length - 1; j++) {
            if (s.Substring(j, 1) == "\n")
                count++;
    }

    Console.WriteLine("The total searches were :" + count);

    fh.Close();

} catch(Exception ex) {
    Console.WriteLine(ex.Message);
}         

Você pode iniciar o executável " wc .exe" ( vem com UnixUtils e não precisa de instalação) executado como um processo externo. Ele suporta diferentes métodos de contagem de linha (como o Unix vs mac vs windows).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top