मिक्स्ड लाइन एंडिंग को ठीक से संभालना मुश्किल है । हम जानते हैं, लाइन समाप्ति वर्ण हो सकते हैं "रेखा फ़ीड" (ASCII 10, \n
, \x0A
, \u000A
), "कैरिज वापसी" (ASCII 13, \r
, \x0D
, \u000D
), या उनमें से कुछ संयोजन। डॉस पर वापस जाने पर, विंडोज दो-चरित्र अनुक्रम सीआर-एलएफ का उपयोग करता है \u000D\u000A
, इसलिए इस संयोजन को केवल एक पंक्ति का उत्सर्जन करना चाहिए। यूनिक्स एक एकल का उपयोग करता है \u000A
, और बहुत पुराने मैक एक एकल \u000D
चरित्र का उपयोग करते हैं । एकल पाठ फ़ाइल के भीतर इन पात्रों के मनमाने मिश्रण का इलाज करने का मानक तरीका निम्नानुसार है:
- प्रत्येक और सीआर या LF चरित्र को अगली पंक्ति EXCEPT पर छोड़ देना चाहिए ...
- ... अगर LF (
\u000D\u000A
) द्वारा एक CR का तुरंत अनुसरण किया जाता है तो ये दोनों एक साथ होंगे सिर्फ एक लाइन छोड़ते हैं।
String.Empty
केवल एक इनपुट है जो कोई रेखा नहीं लौटाता है (कोई भी वर्ण कम से कम एक पंक्ति में प्रवेश करता है)
- अंतिम पंक्ति को लौटाया जाना चाहिए भले ही उसके पास न तो सीआर और न ही एलएफ हो।
पूर्ववर्ती नियम StringReader.ReadLine और संबंधित कार्यों के व्यवहार का वर्णन करता है, और नीचे दिखाए गए फ़ंक्शन समान परिणाम उत्पन्न करते हैं। यह एक कुशल C # लाइन ब्रेकिंग फ़ंक्शन है जो CR-LF के किसी भी मनमाना अनुक्रम या संयोजन को सही ढंग से संभालने के लिए इन दिशानिर्देशों को कर्तव्यपूर्वक लागू करता है। प्रगणित पंक्तियों में कोई CR / LF वर्ण नहीं है। खाली लाइनों को संरक्षित किया जाता है और वापस लौटा दिया जाता है String.Empty
।
/// <summary>
/// Enumerates the text lines from the string.
/// ⁃ Mixed CR-LF scenarios are handled correctly
/// ⁃ String.Empty is returned for each empty line
/// ⁃ No returned string ever contains CR or LF
/// </summary>
public static IEnumerable<String> Lines(this String s)
{
int j = 0, c, i;
char ch;
if ((c = s.Length) > 0)
do
{
for (i = j; (ch = s[j]) != '\r' && ch != '\n' && ++j < c;)
;
yield return s.Substring(i, j - i);
}
while (++j < c && (ch != '\r' || s[j] != '\n' || ++j < c));
}
नोट: यदि आप StringReader
प्रत्येक कॉल पर एक उदाहरण बनाने के ओवरहेड का बुरा नहीं मानते हैं , तो आप इसके बजाय निम्नलिखित C # 7 कोड का उपयोग कर सकते हैं । जैसा कि उल्लेख किया गया है, जबकि ऊपर का उदाहरण थोड़ा अधिक कुशल हो सकता है, ये दोनों कार्य सटीक समान परिणाम उत्पन्न करते हैं।
public static IEnumerable<String> Lines(this String s)
{
using (var tr = new StringReader(s))
while (tr.ReadLine() is String L)
yield return L;
}