لماذا يقوم StreamReader.ReadLine () بإرجاع قيمة لملف سطر واحد بدون سطر جديد؟
-
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 (سلسلة)
يكتب سلسلة متبوعة بمنهي خط إلى دفق النص.