ما هي أسرع طريقة لتحليل النص مع المحددات المخصصة وبعض قيم الحقول جدا، كبيرة جدا في C #؟

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

سؤال

ولقد تم محاولة التعامل مع بعض ملفات نصية محددة التي لها محددات مستوى غير (وليس فاصلة / اقتباس أو علامة التبويب محدد). المحددات هي أحرف ASCII العشوائية التي لا تظهر في كثير من الأحيان بين المحددات. بعد البحث حولها، ولقد يبدو أن لديها وجدت فقط لا حلول في. NET تناسب احتياجاتي والمكتبات العرف أن الناس قد كتب لهذا يبدو أن لديها بعض العيوب عندما يتعلق الأمر لإدخال العملاق (ملف 4GB مع بعض قيم الحقول ذات بسهولة جدا عدة ملايين حرفا).

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

إليك مدخلا سبيل المثال:

Field delimiter = 
quote character = þ

þFieldName1þþFieldName2þþFieldName3þþFieldName4þ
þValue1þþValue2þþValue3þþSomeVery,Very,Very,Large value(5MB or so)þ
...etc...

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

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

المحلول

واستخدم ملف المساعدون API . انها NET و مفتوحة المصدر. انها أداء عالية للغاية باستخدام ترجمة التعليمات البرمجية IL لتحديد المجالات على الأشياء المكتوبة بشدة، ويدعم الدفق.

وهو يدعم جميع أنواع أنواع الملفات والمحددات مخصص؛ لقد استعملت لقراءة ملفات أكبر من 4GB.

إذا لسبب ما لا يفعل ذلك بالنسبة لك، حاول مجرد القراءة سطرا سطرا مع string.split:

public IEnumerable<string[]> CreateEnumerable(StreamReader input)
{
    string line;
    while ((line = input.ReadLine()) != null)
    {
        yield return line.Split('þ');
    }
}

وهذا سوف تعطيك صفائف سلسلة بسيطة تمثل خطوط بطريقة streamy التي يمكنك حتى ينق في.) ولكن تذكر أن IEnumerable هو كسول تحميلها، لذلك لا وثيقة أو تغيير StreamReader حتى كنت قد كرر ( أو تسبب في عملية التحميل الكاملة مثل ToList / ToArray أو مثل -! تعطى حجم الملف الخاص بك ولكن، وأفترض أنك لن تفعل ذلك)

وهنا استخدام نموذج جيد منه:

using (StreamReader sr = new StreamReader("c:\\test.file"))
{
    var qry = from l in CreateEnumerable(sr).Skip(1)
              where l[3].Contains("something")
              select new { Field1 = l[0], Field2 = l[1] };
    foreach (var item in qry)
    {
        Console.WriteLine(item.Field1 + " , " + item.Field2);
    }
}
Console.ReadLine();

وهذا سيتم تخطي خط الرأس، ثم طباعة مجال الأولين من الملف حيث يحتوي حقل 4TH السلسلة "شيء ما". انها لن تفعل هذا دون تحميل الملف بأكمله في الذاكرة.

نصائح أخرى

ويندوز والأداء العالي I / O الوسائل، استخدم <لأ href = "http://blogs.msdn.com/kavitak/archive/2003/12/15/Async-I_2F00_O-and-I_2F00_O-completion-ports. ASPX "يختلط =" نوفولو noreferrer "> IO استكمال الموانئ. قد يكون لديك ما يجب عمله بعض السباكة إضافية للحصول على عمل في قضيتك.

وهذا هو مع التفاهم الذي تريد استخدام C # /. NET، وفقا ل<لأ href = "http://www.bluebytesoftware.com/blog/PermaLink،guid،f8404ab3-e3e6-4933-a5bc- b69348deedba.aspx "يختلط =" نوفولو noreferrer "> جو دافي

<اقتباس فقرة>   

و18) لا تستخدم ويندوز الإجراءات غير متزامن يدعو (ناقلات الجنود المدرعة) في إدارتها   التعليمات البرمجية.

وكان علي أن أتعلم أن واحدا بالطريقة الصعبة؛)، ولكن يستبعد استخدام APC، IOCP هو الحل الوحيد. كما أنه يدعم العديد من أنواع أخرى من I / O، التي يكثر استخدامها في خوادم المقبس.

وبقدر تحليل النص الفعلي، تحقق من <لأ href = "http://blogs.msdn.com/ericwhite/archive/2008/09/30/linq-to-text-and-linq-to- csv.aspx "يختلط =" نوفولو noreferrer "> بلوق اريك الأبيض لاستخدام بعض تيار مبسطة.

وأود أن يميل إلى استخدام مزيج من الذاكرة المعينة الملفات ( MSDN نقطة إلى المجمع. NET هنا ) وتحليل تدريجي بسيط، مما أسفر عن العودة إلى قائمة IEnumerable سجل خطك / النص (أو أيا كان)

ولقد ذكرتم أن بعض الحقول هي كبيرة جدا جدا، إذا حاولت قراءتها في مجملها إلى الذاكرة قد يكون الحصول على نفسك في ورطة. وأود أن يقرأ من خلال الملف في 8K (أو قطع صغيرة)، تحليل المخزن المؤقت الحالي، وتتبع الدولة.

وماذا تحاول أن تفعل مع هذه البيانات التي يتم تحليل؟ هل تبحث عن شيء ما؟ هل تحول ذلك؟

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

و"أناقة" من الواضح أن الشيء شخصي. في رأيي، إذا يبدو API محلل الخاص بك ويعمل مثل BCL "القارئ" معيار API من نوع، ثم وهذا هو تماما "أنيقة".

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

ومثال على كيف يمكن استخدام مثل فئة محلل:

using(var reader = new EddReader(new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, 8192)) {
    // Read a small field
    string smallField = reader.ReadFieldAsText();
    // Read a large field
    Stream largeField = reader.ReadFieldAsStream();
}

ولئن كان هذا لا يساعد معالجة مسألة مساهمة كبيرة، والحلول الممكنة لقضية الاعراب قد تشمل محلل مخصص للمستخدمين نمط استراتيجية لتوريد محدد.

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