Determinar o número de linhas dentro de um arquivo de texto

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

Edição seriamente tardia: se você estiver usando o .NET 4.0 ou posterior

A class File tem um novo método ReadLines que enumera lazily linhas em vez de ler todas elas em uma matriz como ReadAllLines . Então agora você pode ter 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, você poderia fazer:

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

Edit: Em resposta a perguntas sobre eficiência

A razão pela qual eu disse que o segundo era mais eficiente era com relação ao uso da memory, não necessariamente à velocidade. O primeiro carrega todo o conteúdo do arquivo em uma matriz, o que significa que deve alocar pelo menos a mesma quantidade de memory que o tamanho do arquivo. O segundo apenas faz um loop de uma linha de cada vez, para que nunca tenha que alocar mais de uma linha de memory por vez. Isso não é tão importante para arquivos pequenos, mas para arquivos maiores pode ser um problema (se você tentar encontrar o número de linhas em um arquivo de 4GB em um sistema de 32 bits, por exemplo, onde simplesmente não há o suficiente espaço de endereço no modo de usuário para alocar um array tão grande).

Em termos de velocidade, eu não esperaria muito nele. É possível que ReadAllLines tenha algumas otimizações internas, mas, por outro lado, pode ter que alocar um grande pedaço de memory. Eu acho que ReadAllLines pode ser mais rápido para arquivos pequenos, mas significativamente mais lento para arquivos grandes; embora a única maneira de saber seria medir com um Cronômetro ou um gerador de código.

O mais fácil:

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

Isso usaria menos memory, mas provavelmente levaria mais tempo

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

Se por facilidade você quer dizer linhas de código fáceis de decifrar, mas por acaso ineficientes?

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

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

Você também pode fazer (dependendo se você está armazenando em buffer)

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

Existem outras maneiras, mas uma das opções acima é provavelmente o que você irá usar.

Você pode rapidamente ler e incrementar um contador, basta usar um loop para incrementar, sem fazer nada com o texto.

conte os retornos de carro / alimentações de linha. Eu acredito que em unicode eles ainda são 0x000D e 0x000A, respectivamente. Dessa forma, você pode ser tão eficiente ou ineficiente quanto quiser e decidir se precisa lidar com os dois personagens ou não

Uma opção viável, e uma que usei pessoalmente, seria adicionar seu próprio header à primeira linha do arquivo. Eu fiz isso para um formato de modelo personalizado para o meu jogo. Basicamente, eu tenho uma ferramenta que otimiza meus arquivos .obj, me livrando da porcaria que não preciso, os converte em um layout melhor, e então escreve o número total de linhas, faces, normais, vértices e UVs de textura em a primeira linha. Esses dados são usados ​​por vários buffers de matriz quando o modelo é carregado.

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

Eu tentei maneiras diferentes e o mais rápido se você tiver um arquivo muito grande é:

 var counter = 0; using (var file = new StreamReader(@"file.txt")) { while (file.ReadLine() != null) { counter++; } } 

Lendo um arquivo e por si só leva algum tempo, garbage collection, o resultado é outro problema que você lê todo o arquivo apenas para contar o caractere de nova linha,

Em algum momento, alguém terá que ler os caracteres no arquivo, independentemente se este for o framework ou se for o seu código. Isso significa que você tem que abrir o arquivo e lê-lo na memory, se o arquivo for grande, isso pode ser um problema, já que a memory precisa ser coletada como lixo.

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

Aqui está a solução proposta, pois ela lê 4 caracteres por vez, conta o caractere de alimentação de linha e reutiliza o mesmo endereço de memory novamente para a próxima comparação de caracteres.

 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 é lida um caractere de cada vez, também pelo framework subjacente, já que você precisa ler todos os caracteres para ver o avanço de linha.

Se você fizer o perfil como done bay Nima, verá que essa é uma maneira 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. Suporta diferentes methods de contagem de linhas (como unix vs mac vs windows).