Определить количество строк в текстовом файле

Есть ли простой способ программно определить количество строк в текстовом файле?

Ответ 1

Серьезно запоздалое редактирование: если вы используете .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 может быть быстрее для небольших файлов, но значительно медленнее для больших файлов; хотя единственный способ сказать - измерить его с помощью секундомера или профайлера кода.

Ответ 2

Самый простой:

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

Ответ 3

Это будет использовать меньше памяти, но, вероятно, займет больше времени

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

Ответ 4

Если вы легко понимаете строки кода, которые легко расшифровать, но на случай неэффективности?

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

Есть и другие многочисленные способы, но один из вышеперечисленных - это, вероятно, то, с чем вы будете идти.

Ответ 5

Вы можете быстро прочитать его и увеличить счетчик, просто используйте цикл для увеличения, ничего не делая с текстом.

Ответ 6

подсчет возвратов каретки/строк. Я считаю, что в юникоде они все равно 0x000D и 0x000A соответственно. таким образом, вы можете быть такими же эффективными или неэффективными, как вы хотите, и решить, нужно ли иметь дело с обоими символами или нет.

Ответ 7

Жизнеспособный вариант и тот, который я лично использовал, - это добавить свой собственный заголовок в первую строку файла. Я сделал это для пользовательского формата модели для своей игры. В принципе, у меня есть инструмент, который оптимизирует мои файлы .obj, избавляясь от дерьма, в котором я не нуждаюсь, преобразует их в лучший макет, а затем записывает общее количество строк, граней, нормалей, вершин и текстурных UVs на самая первая строка. Эти данные затем используются буферами различных массивов при загрузке модели.

Это также полезно, потому что вам нужно только один раз пропустить файл, чтобы загрузить его, а не один раз, чтобы подсчитать строки, и снова прочитать данные в созданных буферах.

Ответ 8

Чтение файла и само по себе занимает некоторое время, сбор мусора результата - это еще одна проблема, поскольку вы читаете весь файл только для подсчета символов (строк) новой строки,

В какой-то момент кто-то должен будет прочитать символы в файле, независимо от того, является ли это каркасом или является вашим кодом. Это означает, что вы должны открыть файл и прочитать его в памяти, если файл большой, это потенциально может быть проблемой, поскольку память должна быть собрана мусором.

Нима Ара сделал хороший анализ, который вы могли бы принять во внимание

Вот предлагаемое решение, так как оно читает по 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;
}

Выше видно, что строка читается по одному символу за раз, а также по базовой структуре, поскольку вам нужно прочитать все символы, чтобы увидеть фид строки.

Если вы прокомментируете это как сделанный отсек Нима, вы увидите, что это довольно быстрый и эффективный способ сделать это.

Ответ 9

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

Ответ 10

Я пробовал разные способы и самый быстрый, если у вас очень большой файл:

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

Ответ 11

Вы можете запустить " wc.exe" исполняемый файл (поставляется с UnixUtils и не требует установки) запускается как внешний процесс. Он поддерживает различные методы подсчета строк (например, unix vs mac vs windows).