Determina il numero di linee all’interno di un file di testo

C’è un modo semplice per determinare a livello di codice il numero di righe all’interno di un file di testo?

Modifica seriamente ritardata: se stai usando .NET 4.0 o versioni successive

La class File ha un nuovo metodo ReadLines che enfatizza pigramente le righe piuttosto che leggerle tutte in una matrice come ReadAllLines . Quindi ora puoi avere sia efficienza che concisione con:

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

Risposta originale

Se non sei troppo preoccupato dell’efficienza, puoi semplicemente scrivere:

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

Per un metodo più efficiente si potrebbe fare:

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

Modifica: in risposta alle domande sull’efficienza

Il motivo per cui ho detto che il secondo era più efficiente riguardava l’utilizzo della memoria, non necessariamente la velocità. Il primo carica l’intero contenuto del file in un array, il che significa che deve allocare almeno la stessa quantità di memoria della dimensione del file. Il secondo ruota semplicemente una linea alla volta, quindi non deve mai allocare più di una riga di memoria alla volta. Questo non è così importante per i file di piccole dimensioni, ma per i file più grandi potrebbe essere un problema (se si prova a trovare il numero di righe in un file da 4 GB su un sistema a 32 bit, ad esempio, dove semplicemente non è abbastanza spazio di indirizzamento in modalità utente per allocare un array così grande).

In termini di velocità, non mi aspetto che ci sia molto. È ansible che ReadAllLines abbia alcune ottimizzazioni interne, ma d’altra parte potrebbe dover allocare una grande quantità di memoria. Direi che ReadAllLines potrebbe essere più veloce per i file di piccole dimensioni, ma molto più lento per i file di grandi dimensioni; anche se l’unico modo per dirlo sarebbe misurarlo con un cronometro o un profiler del codice.

Il più facile:

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

Ciò userebbe meno memoria, ma probabilmente richiedere più tempo

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

Se per semplicità intendi linee di codice facili da decifrare ma per caso inefficienti?

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

Questo è probabilmente il modo più veloce per sapere quante linee.

Si potrebbe anche fare (a seconda se lo si sta bufferizzando)

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

Ci sono molti altri modi, ma uno dei precedenti è probabilmente quello che andrai con.

Puoi leggerlo rapidamente e incrementare un contatore, basta usare un ciclo per incrementare, senza fare nulla con il testo.

conta i ritorni a capo / gli avanzamenti di riga. Credo che in unicode siano ancora 0x000D e 0x000A rispettivamente. in questo modo puoi essere efficiente o inefficiente quanto vuoi e decidere se devi occuparti di entrambi i personaggi o meno

Un’opzione valida, e che ho usato personalmente, sarebbe quella di aggiungere la propria intestazione alla prima riga del file. L’ho fatto per un formato di modello personalizzato per il mio gioco. Fondamentalmente, ho uno strumento che ottimizza i miei file .obj, sbarazzandomi della merda di cui non ho bisogno, li converto in un layout migliore, e poi scrive il numero totale di linee, facce, normali, vertici e texture UV su la primissima linea. Questi dati vengono quindi utilizzati da vari buffer di array quando viene caricato il modello.

Ciò è utile anche perché è sufficiente eseguire il loop del file una sola volta per caricarlo, anziché una volta per contare le righe, e di nuovo per leggere i dati nei buffer creati.

Ho provato diversi modi e il più veloce se hai file di grandi dimensioni è:

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

La lettura di un file e da sola richiede un po ‘di tempo, la raccolta dei dati inutili è un altro problema mentre leggi l’intero file solo per contare i caratteri di nuova riga,

Ad un certo punto, qualcuno dovrà leggere i caratteri nel file, indipendentemente se questo sia il framework o se sia il tuo codice. Ciò significa che devi aprire il file e leggerlo in memoria se il file è di grandi dimensioni questo potrebbe essere un problema in quanto la memoria deve essere raccolta.

Nima Ara ha fatto una bella analisi che potresti prendere in considerazione

Ecco la soluzione proposta, in quanto legge 4 caratteri alla volta, conta il carattere di avanzamento riga e riutilizza lo stesso indirizzo di memoria per il successivo confronto dei caratteri.

 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; } 

Qui sopra puoi vedere che una riga viene letta un carattere alla volta e dal framework sottostante in quanto è necessario leggere tutti i caratteri per vedere il feed di riga.

Se lo profilassi come completato Nima, vedresti che questo è un modo abbastanza veloce ed efficiente per farlo.

 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); } 

È ansible avviare l’eseguibile ” wc .exe” (fornito con UnixUtils e non necessita di installazione) eseguito come processo esterno. Supporta diversi metodi di conteggio delle righe (come Unix vs Mac vs Windows).