لماذا يقوم StreamReader.ReadLine () بإرجاع قيمة لملف سطر واحد بدون سطر جديد؟

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

  •  27-09-2019
  •  | 
  •  

سؤال

أريد إلحاق ملفين نصين معًا.

لدي ملف واحد مع خلاصة سطر إرجاع النقل في النهاية. مراقبة الملف A وهو 28 بايت.

هذا سطر في الملف n

ثم لدي ملف آخر هو نفس الشيء بدون الخط الجديد. مراقبة الملف ب وهو 26 بايت.

هذا سطر في الملف

أرغب في إلحاق نفس الملف لنفسه (ملف إلى A ، والملف B إلى B) ومقارنة تعداد البايت.

ومع ذلك ، عند استخدام StreamReader.ReadLine() في الملف A ، أحصل على قيمة إرجاع لكن MSDN تقول:

يتم تعريف الخط على أنه سلسلة من الأحرف متبوعة بتغذية سطر (" n") ، أو عودة النقل (" r") أو عودة عربة تليها على الفور خلاصة خط (" r n"). لا تحتوي السلسلة التي يتم إرجاعها على إرجاع النقل أو تغذية الخط. القيمة التي تم إرجاعها لاغية إذا تم الوصول إلى نهاية دفق الإدخال.

ومع ذلك ، لا يوجد CRLF في الملف.

كيف يمكنني إلحاق هذه الملفات بأمان دون إضافة كسر خط إضافي في النهاية؟ علي سبيل المثال، StreamWriter.WriteLine() سأضع استراحة سطر إضافية في الملف A عندما لا أريد ذلك. ماذا سيكون مقاربة مثالية؟

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

المحلول

StreamReader و StreamWriter (التي تستمد من Textreader و TextWriter) ليست مناسبة للحالات التي تتطلب شكلًا دقيقًا من البيانات الثنائية. إنها تجريدات عالية المستوى لملف يتكون من بايت ، وليس نصًا أو خطوطًا. في الواقع ، لا يمكن أن تنتهي فقط بعدد مختلف من الخطوط الجديدة ، ولكن بناءً على البيئة ، يمكنك كتابة منهيات الخط بخلاف CR/LF المتوقع.

يجب عليك بدلاً من ذلك مجرد نسخ من دفق إلى آخر. هذا سهل للغاية في الواقع.

var bytes = File.ReadAllBytes(pathIn);
var stream = File.Open(pathOut, FileMode.Append);
stream.Write(bytes, 0, bytes.Length);
stream.Close();

إذا كان حجم الملف كبيرًا ، فيجب عليك فتح كل من ملف الإدخال والإخراج في نفس الوقت واستخدام المخزن المؤقت ثابت الحجم لنسخ كتلة في وقت واحد.

using (var streamIn = File.Open(pathIn, FileMode.Read))
using (var streamOut = File.Open(pathOut, FileMode.Append)) {

    var bytes = new byte[BLOCK_SIZE];

    int count;
    while ((count=streamIn.Read(bytes, 0, bytes.Length)) > 0) {
        streamOut.Write(bytes, 0, count);
    }

}

تجدر الإشارة أيضًا إلى أنه يمكن استبدال الكود أعلاه Stream.copyto وهو جديد في .NET 4.

نصائح أخرى

ستحصل فقط null إذا اتصلت ReadLine في نهاية الدفق. خلاف ذلك ، ستحصل على جميع البيانات حتى أيضاً أ CRLF أو نهاية الدفق.

إذا كنت تحاول القيام بتكرار بايت مقابل بايت (والمقارنة) ، فمن الأفضل لك قراءة أي شخصين (باستخدام StreamReader/StreamWriter أثناء استخدامك الآن) أو بايت (باستخدام فقط باستخدام Stream الفصل) باستخدام العادي Read و Write وظائف بدلا من ReadLine و WriteLine.

يمكنك أيضًا قراءة محتويات الملف بأكملها باستخدام ReadToEnd ثم اكتبها عن طريق الاتصال Write (ليس WriteLine) ، على الرغم من أن هذا ليس عمليًا إذا كان الملف كبيرًا.

string data;

using(StreamReader reader = new StreamReader(path))
{
    data = reader.ReadToEnd();
}

using(StreamWriter writer = new StreamWriter(path, true))
{
    writer.Write(data);
}

يمكنك استخدام StreamWriter.write بدلاً من WriteLine لتجنب CRLF الإضافي.

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

حسنًا ، يعتمد الأمر حقًا على أسباب تنفيذك (لماذا تقرأه عن طريق الخط وكتابته الخلفية سطرًا؟) يمكنك استخدامك فقط StreamWriter.Write(string) وإخراج كل النص الذي قمت بتخزينه ، WriteLine() تتم تسمية الأساليب على هذا النحو لأنها إلحاق سطر جديد.

TextWriter.WriteLine Method (سلسلة)
يكتب سلسلة متبوعة بمنهي خط إلى دفق النص.

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