Відповіді:
Серйозно запізніла редакція. Якщо ви використовуєте .NET 4.0 або новішу версію
У File
класі є новий ReadLines
метод, який ліниво перераховує рядки, а не жадібно читати їх усі в масив на зразок ReadAllLines
. Тож тепер ви можете мати як ефективність, так і стислість з:
var lineCount = File.ReadLines(@"C:\file.txt").Count();
Оригінальний відповідь
Якщо ви не надто переймаєтесь ефективністю, можете просто написати:
var lineCount = File.ReadAllLines(@"C:\file.txt").Length;
Для більш ефективного методу ви можете:
var lineCount = 0;
using (var reader = File.OpenText(@"C:\file.txt"))
{
while (reader.ReadLine() != null)
{
lineCount++;
}
}
Редагувати: У відповідь на запитання про ефективність
Причина, по якій я сказав, що друга була більш ефективною, стосувалася використання пам’яті, не обов'язково швидкості. Перший завантажує весь вміст файлу в масив, що означає, що він повинен виділяти принаймні стільки пам'яті, скільки розмір файлу. Другий лише циклічно обводить один рядок, і ніколи не потрібно виділяти більше, ніж пам'ять, ніж одна лінія. Це не так важливо для невеликих файлів, але для великих файлів це може бути проблемою (якщо спробувати знайти кількість рядків у файлі 4 Гб у 32-бітній системі, наприклад, де просто недостатньо адресний простір в режимі користувача, щоб виділити масив такий великий).
З точки зору швидкості, я б не очікував, що в ньому буде багато. Цілком можливо, що ReadAllLines має деякі внутрішні оптимізації, але з іншого боку, можливо, доведеться виділити величезний фрагмент пам'яті. Я думаю, що ReadAllLines може бути швидшим для невеликих файлів, але значно повільніше для великих файлів; хоча єдиний спосіб сказати - це виміряти його секундоміром або кодовим профілером.
ReadLines().Count()
вам потрібно буде додати using System.Linq
до своїх включень. Здавалося, досить неінтуїтивно вимагати цього доповнення, тому я його згадую. Якщо ви використовуєте Visual Studio, швидше за все, це додавання буде зроблено автоматично.
Якщо просто ви маєте на увазі рядки коду, які легко розшифрувати, але на шанс неефективні?
string[] lines = System.IO.File.RealAllLines($filename);
int cnt = lines.Count();
Це, мабуть, найшвидший спосіб дізнатися, скільки рядків.
Ви також можете зробити це (залежно від того, чи буферизуєте ви це)
#for large files
while (...reads into buffer){
string[] lines = Regex.Split(buffer,System.Enviorment.NewLine);
}
Є й інші численні способи, але один із перерахованих вище - це, мабуть, те, з чим ви підете.
Ви можете швидко прочитати його та збільшити лічильник, просто використайте цикл для збільшення, нічого не роблячи з текстом.
Читання файлу саме по собі займає певний час, а збирання сміття - це ще одна проблема, коли ви читаєте весь файл лише для підрахунку символів (символів) нового рядка,
У якийсь момент комусь доведеться читати символи у файлі, незалежно від того, це рамки чи це ваш код. Це означає, що вам потрібно відкрити файл і прочитати його в пам'яті, якщо файл великий, це потенційно може бути проблемою, оскільки пам'ять потрібно збирати сміття.
Німа Ара зробив хороший аналіз, який ви можете взяти до уваги
Ось запропоноване рішення, оскільки воно читає одночасно 4 символи, підраховує символ подачі рядка і знову використовує ту саму адресу пам'яті для наступного порівняння символів.
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;
}
Вище видно, що рядок читається один символ одночасно, а також базовим фреймом, оскільки вам потрібно прочитати всі символи, щоб побачити канал рядка.
Якщо ви профілюєте це як виконаний залив Німа, то ви побачите, що це досить швидкий і ефективний спосіб зробити це.
Важливим варіантом, який я особисто використав, було б додати власний заголовок до першого рядка файлу. Я зробив це для індивідуального формату моделі для своєї гри. В основному, у мене є інструмент, який оптимізує мої файли .obj, позбавляючись від непотрібних мені лайнів, перетворює їх на кращу компоновку, а потім записує загальну кількість рядків, облич, нормалів, вершин і текстурних УФ на найперший рядок. Ці дані потім використовуються різними буферами масиву під час завантаження моделі.
Це також корисно, оскільки вам потрібно лише один раз прокрутити файл, щоб завантажити його, замість того, щоб один раз рахувати рядки, і знову читати дані у створених буферах.
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);
}
Ви можете запустити виконуваний файл " wc .exe" (постачається разом з UnixUtils і не потребує встановлення), запустившись як зовнішній процес. Він підтримує різні методи підрахунку рядків (наприклад, Unix проти Mac проти Windows).