سؤال

هل هناك طريقة سهلة لتحديد عدد الأسطر داخل ملف نصي برمجياً؟

هل كانت مفيدة؟

المحلول

تعديل متأخر جدًا:إذا كنت تستخدم .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);
}

هناك العديد من الطرق الأخرى ولكن ربما تكون إحدى الطرق المذكورة أعلاه هي ما ستختاره.

يمكنك قراءتها بسرعة وزيادة العداد، فقط استخدم حلقة لزيادة، دون القيام بأي شيء مع النص.

حساب إرجاعات السطر/موجزات الأسطر.أعتقد أن Unicode لا يزالان 0x000D و0x000A على التوالي.وبهذه الطريقة يمكنك أن تكون فعالاً أو غير فعال كما تريد، وتقرر ما إذا كان عليك التعامل مع كلا الشخصيتين أم لا

الخيار القابل للتطبيق، والذي استخدمته شخصيًا، هو إضافة رأسك الخاص إلى السطر الأول من الملف.لقد فعلت ذلك من أجل تنسيق نموذج مخصص للعبتي.في الأساس، لدي أداة تعمل على تحسين ملفات .obj الخاصة بي، والتخلص من الأشياء التي لا أحتاج إليها، وتحويلها إلى تخطيط أفضل، ثم كتابة العدد الإجمالي للخطوط، والوجوه، والأوضاع الطبيعية، والقمم، والملمس فوق البنفسجي على السطر الأول.يتم بعد ذلك استخدام هذه البيانات بواسطة مخازن مؤقتة مختلفة للصفيف عند تحميل النموذج.

يعد هذا مفيدًا أيضًا لأنك تحتاج فقط إلى تكرار الملف مرة واحدة لتحميله، بدلاً من مرة واحدة لحساب الأسطر، ومرة ​​أخرى لقراءة البيانات في المخازن المؤقتة التي قمت بإنشائها.

تستغرق قراءة الملف بمفرده بعض الوقت، كما أن جمع البيانات المهملة يمثل مشكلة أخرى حيث أنك تقرأ الملف بأكمله فقط لحساب حرف (أحرف) السطر الجديد،

في مرحلة ما، سيتعين على شخص ما قراءة الأحرف الموجودة في الملف، بغض النظر عما إذا كان هذا هو إطار العمل أو ما إذا كان هذا هو الكود الخاص بك.هذا يعني أنه يتعين عليك فتح الملف وقراءته في الذاكرة. إذا كان الملف كبيرًا، فمن المحتمل أن يكون هذا مشكلة لأن الذاكرة تحتاج إلى تجميع البيانات المهملة.

قدمت Nima Ara تحليلاً لطيفًا قد تأخذه بعين الاعتبار

إليك الحل المقترح، حيث يقرأ 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;
}

أعلاه يمكنك أن ترى أن السطر يُقرأ حرفًا واحدًا في كل مرة أيضًا من خلال الإطار الأساسي حيث تحتاج إلى قراءة جميع الأحرف لرؤية تغذية السطر.

إذا قمت بتوصيفها كما فعلت Bay Nima، فسترى أن هذه طريقة سريعة وفعالة للقيام بذلك.

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 vs mac vs windows).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top