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

StackOverflow https://stackoverflow.com/questions/119559

  •  02-07-2019
  •  | 
  •  

Вопрос

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

Это было полезно?

Решение

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

Другие советы

Простейший:

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

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

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

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

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

Существует множество других способов, но вам, вероятно, подойдет один из вышеперечисленных.

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

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

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

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

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

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

Нима Ара провела хороший анализ, который вы можете принять во внимание.

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

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

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

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

Вы можете запустить "Туалет.exe» исполняемый файл (поставляется с UnixUtils и не требует установки) запускается как внешний процесс.Он поддерживает различные методы подсчета строк (например, Unix, Mac и Windows).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top