.NET में newlines पर एक स्ट्रिंग को विभाजित करने का सबसे आसान तरीका?


806

मुझे .NET में newlines में एक स्ट्रिंग को विभाजित करने की आवश्यकता है और मुझे विभाजन को विभाजित करने का एकमात्र तरीका स्प्लिट विधि के साथ है। हालाँकि, यह मुझे (आसानी से) एक नई रेखा पर विभाजित करने की अनुमति नहीं देगा, इसलिए इसे करने का सबसे अच्छा तरीका क्या है?


2
ऐसा क्यों नहीं होगा? बस System.Environment.NewLine पर विभाजित करें
aviraldg

16
लेकिन आपको इसे एक स्ट्रिंग में लपेटना होगा [] और एक अतिरिक्त तर्क जोड़ना होगा और ... यह सिर्फ भद्दा लगता है।
RCIX

जवाबों:


1411

एक स्ट्रिंग पर विभाजित करने के लिए आपको उन अधिभार का उपयोग करने की आवश्यकता होती है जो स्ट्रिंग की एक सरणी लेता है:

string[] lines = theText.Split(
    new[] { Environment.NewLine },
    StringSplitOptions.None
);

संपादित करें:
यदि आप किसी पाठ में विभिन्न प्रकार के लाइन ब्रेक को हैंडल करना चाहते हैं, तो आप एक से अधिक स्ट्रिंग से मिलान करने की क्षमता का उपयोग कर सकते हैं। यह सही प्रकार के लाइन ब्रेक पर विभाजित हो जाएगा, और पाठ में खाली लाइनों और रिक्ति को संरक्षित करेगा:

string[] lines = theText.Split(
    new[] { "\r\n", "\r", "\n" },
    StringSplitOptions.None
);

3
@RCIX: सही पैरामीटर को विधि में भेजना थोड़ा अजीब है क्योंकि आप इसे किसी ऐसी चीज के लिए उपयोग कर रहे हैं जो कि इसके लिए बहुत सरल है। कम से कम यह वहाँ है, फ्रेमवर्क 2 से पहले आपको एक नियमित अभिव्यक्ति का उपयोग करना था या एक स्ट्रिंग पर विभाजित करने के लिए अपनी खुद की विभाजनकारी दिनचर्या का निर्माण करना था ...
गुफ़ा

4
@ लिंड्रो: Environment.NewLineसंपत्ति में सिस्टम के लिए डिफ़ॉल्ट न्यूलाइन है। उदाहरण के लिए एक विंडोज सिस्टम के लिए यह होगा "\r\n"
गुफ्ना

3
@Leandro: एक अनुमान होगा कि पर कार्यक्रम विभाजन \nएक छोड़ने \rप्रत्येक पंक्ति के अंत में है, तो एक साथ लाइनों आउटपुट \r\nउन दोनों के बीच।
गुफ़ा

3
@ सैमुअल: \rऔर \nएस्केप सीक्वेंस (दूसरों के बीच) C # कंपाइलर का एक विशेष अर्थ है। VB में वे क्रम नहीं हैं, इसलिए वहां उन स्थिरांक का उपयोग किया जाता है।
गुफा जूल 25'13

2
यदि आप विभिन्न OS के बहुत से फ़ाइलों को स्वीकार करना चाहते हैं, तो आप "\ n \" को प्रारंभ में और "\ r" को सीमांकक सूची के अंत में जोड़ सकते हैं। मुझे यकीन नहीं है कि यह प्रदर्शन हिट के लायक है। ( en.wikipedia.org/wiki/Newline )
user420667

121

का उपयोग करने के बारे में क्या StringReader?

using (System.IO.StringReader reader = new System.IO.StringReader(input)) {
    string line = reader.ReadLine();
}

13
यह मेरा मनपसंद है। मैं एक विस्तार विधि में लिपटे और उपज वर्तमान लाइन: gist.github.com/ronnieoverby/7916886
Ronnie Overby

3
यह एकमात्र गैर-रेगेक्स समाधान है जो मैंने .netcf 3.5
कार्ल

8
विशेष रूप से अच्छा है जब इनपुट बड़ा है और इसे एक सरणी में कॉपी करना धीमा / स्मृति गहन हो जाता है।
एलेजैंड्रो 19

1
जैसा कि लिखा गया है, यह उत्तर केवल पहली पंक्ति को पढ़ता है। स्टीव कूपर केwhile लूप के उत्तर को देखें जिसे इस उत्तर में जोड़ा जाना चाहिए।
टूलमेकरसैट

48

आपको अपनी स्ट्रिंग को आसानी से विभाजित करने में सक्षम होना चाहिए, जैसे:

aString.Split(Environment.NewLine.ToCharArray());

46
एक गैर-* nix प्रणाली पर जो अलग-अलग वर्णों पर Newline स्ट्रिंग, यानी CR और LF वर्णों में विभाजित होगी। यह प्रत्येक पंक्ति के बीच एक अतिरिक्त रिक्त स्ट्रिंग का कारण होगा।
गुफ़ा

मुझे सही है अगर मैं गलत हूँ, लेकिन यह अक्षर \ और n पर विभाजित नहीं होगा?
RCIX

7
@RCIX: नहीं, \ r और \ n कोड एकल वर्णों का प्रतिनिधित्व करते हैं। स्ट्रिंग "\ r \ n" दो अक्षर हैं, चार नहीं।
गुफ़ा

10
यदि आप पैरामीटर StringSplitOptions.RemoveEmptyEntries जोड़ते हैं, तो यह पूरी तरह से काम करेगा।
रुबेन

18
@ रूबेन: नहीं, यह नहीं होगा। सर्ज ने पहले ही सुझाव दिया था कि उनके जवाब में, और मैंने पहले ही समझाया है कि यह मूल पाठ में खाली लाइनों को भी हटा देगा जिसे संरक्षित किया जाना चाहिए।
गुफ्ता

34

एक सामान्य समाधान के लिए string.Split का उपयोग करने से बचने की कोशिश करें, क्योंकि आप हर जगह फ़ंक्शन का उपयोग करने के लिए अधिक मेमोरी का उपयोग करेंगे - मूल स्ट्रिंग, और स्प्लिट कॉपी, दोनों मेमोरी में। मेरा विश्वास करो कि जब आप स्केल करना शुरू करते हैं तो यह एक समस्या का एक नरक हो सकता है - एक 32-बिट बैच-प्रसंस्करण एप्लिकेशन को 100 एमबी दस्तावेजों को चलाने के लिए, और आप आठ समवर्ती थ्रेड्स में बकवास करेंगे। ऐसा नहीं है कि मैं इससे पहले वहाँ गया था ...

इसके बजाय, इस तरह से एक पुनरावृत्ति का उपयोग करें;

    public static IEnumerable<string> SplitToLines(this string input)
    {
        if (input == null)
        {
            yield break;
        }

        using (System.IO.StringReader reader = new System.IO.StringReader(input))
        {
            string line;
            while( (line = reader.ReadLine()) != null)
            {
                yield return line;
            }
        }
    }

यह आपको अपने डेटा के आसपास अधिक मेमोरी कुशल लूप करने की अनुमति देगा;

foreach(var line in document.SplitToLines()) 
{
    // one line at a time...
}

बेशक, यदि आप यह सब स्मृति में चाहते हैं, तो आप यह कर सकते हैं;

var allTheLines = document.SplitToLines.ToArray();

मैं वहां गया हूं ... (बड़ी HTML फ़ाइलों को पार्स करना और मेमोरी से बाहर चलना)। हाँ, स्ट्रिंग से बचें। String.Split का उपयोग करने से बड़े ऑब्जेक्ट हीप (LOH) का उपयोग हो सकता है - लेकिन मैं इसके बारे में 100% निश्चित नहीं हूं।
पीटर मोर्टेंसन

यदि आपने स्प्लिट टॉयलाइन को एक स्थिर विधि बनाया है (जो आपको लगता है कि यह dd है), तो आप blah.SplitToLines.. उदा कैसे कर सकते हैं document.SplitToLines...?
बार्लोप

आह मुझे लगता है कि आप thisऔपचारिक मापदंडों में इसे विस्तार विधि बना रहे हैं।
बार्लोप १४'१

26

एक विस्तार वर्ग में गुफ़ा के उत्तर के आधार पर, उपयोग करें:

public static string[] Lines(this string source) {
    return source.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
}

9

एक स्ट्रिंग चर के लिए s:

s.Split(new string[]{Environment.NewLine},StringSplitOptions.None)

यह आपके पर्यावरण की लाइन एंडिंग की परिभाषा का उपयोग करता है। विंडोज पर, लाइन एंडिंग CR-LF (कैरिज रिटर्न, लाइन फीड) या C # के एस्केप कैरेक्टर्स में हैं \r\n

यह एक विश्वसनीय समाधान है, क्योंकि यदि आप लाइनों को फिर से जोड़ते हैं String.Join, तो यह आपके मूल स्ट्रिंग के बराबर है:

var lines = s.Split(new string[]{Environment.NewLine},StringSplitOptions.None);
var reconstituted = String.Join(Environment.NewLine,lines);
Debug.Assert(s==reconstituted);

क्या नहीं कर सकते है:

  • उपयोग करें StringSplitOptions.RemoveEmptyEntries, क्योंकि यह मार्कअप जैसे मार्कअप को तोड़ देगा जहां खाली लाइनों का वाक्यिक उद्देश्य होता है।
  • विभाजक पर विभाजित करें new char[]{Environment.NewLine}, क्योंकि विंडोज पर यह प्रत्येक नई लाइन के लिए एक खाली स्ट्रिंग तत्व बनाएगा।

मूल रूप से शीर्ष रेटेड के रूप में यहां एक ही जवाब, एक को स्वीकार किया गया, लेकिन इसमें एक अच्छी इकाई परीक्षण और कैवेट है।
vapcguy

8

Regex भी एक विकल्प है:

    private string[] SplitStringByLineFeed(string inpString)
    {
        string[] locResult = Regex.Split(inpString, "[\r\n]+");
        return locResult;
    }

7
यदि आप लाइनों को बिल्कुल मेल खाना चाहते हैं, तो रिक्त लाइनों को संरक्षित करते हुए, यह रेगेक्स स्ट्रिंग बेहतर होगा "\r?\n":।
रोरी ओ'केन

7

मैंने सोचा था कि मैं अपने दो-बिट जोड़ दूंगा, क्योंकि इस प्रश्न के अन्य समाधान पुन: प्रयोज्य कोड वर्गीकरण में नहीं आते हैं और सुविधाजनक नहीं हैं।

कोड का निम्नलिखित ब्लॉक stringऑब्जेक्ट को बढ़ाता है ताकि स्ट्रिंग्स के साथ काम करते समय यह एक प्राकृतिक विधि के रूप में उपलब्ध हो।

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using System.Collections.ObjectModel;

namespace System
{
    public static class StringExtensions
    {
        public static string[] Split(this string s, string delimiter, StringSplitOptions options = StringSplitOptions.None)
        {
            return s.Split(new string[] { delimiter }, options);
        }
    }
}

अब आप .Split()किसी भी स्ट्रिंग से फ़ंक्शन का उपयोग इस प्रकार कर सकते हैं :

string[] result;

// Pass a string, and the delimiter
result = string.Split("My simple string", " ");

// Split an existing string by delimiter only
string foo = "my - string - i - want - split";
result = foo.Split("-");

// You can even pass the split options parameter. When omitted it is
// set to StringSplitOptions.None
result = foo.Split("-", StringSplitOptions.RemoveEmptyEntries);

एक नई रेखा वर्ण पर विभाजित करने के लिए, बस पास "\n"या "\r\n"परिसीमन पैरामीटर के रूप में।

टिप्पणी: यदि Microsoft ने इस अधिभार को लागू किया तो अच्छा होगा।


Environment.Newline\nया तो हार्ड-कोडिंग के लिए पसंद किया जाता है या \r\n
माइकल ब्लैकबर्न

3
@MichaelBlackburn - यह एक अमान्य कथन है क्योंकि कोई संदर्भ नहीं है। Environment.Newlineक्रॉस प्लेटफ़ॉर्म कॉम्पैटिबिलिटी के लिए है, वर्तमान ऑपरेटिंग सिस्टम की तुलना में विभिन्न लाइन समाप्ति का उपयोग करने वाली फ़ाइलों के साथ काम करने के लिए नहीं। अधिक जानकारी के लिए यहां देखें , इसलिए यह वास्तव में इस बात पर निर्भर करता है कि डेवलपर किसके साथ काम कर रहा है। उपयोग की Environment.Newlineसुनिश्चित वहाँ ओएस के बीच की रेखा वापसी प्रकार, जहां 'हार्ड-कोड' डेवलपर पूर्ण नियंत्रण देता है में कोई निरंतरता है।
क्रैंग प्राइम

2
@MichaelBlackburn - आपको अशिष्ट होने की कोई आवश्यकता नहीं है। मैं केवल जानकारी प्रदान कर रहा था। .Newlineजादू नहीं है, हुड के तहत यह सिर्फ तार है जैसा कि एक स्विच के आधार पर ऊपर प्रदान किया गया है यदि यह यूनिक्स पर चल रहा है, या खिड़कियों पर। सबसे सुरक्षित शर्त, पहले एक स्ट्रिंग को सभी "\ r \ n" के लिए बदलना है और फिर "\ n" पर विभाजित करना है। जहां .Newlineफेल का उपयोग करना है, जब आप उन फ़ाइलों के साथ काम कर रहे हैं जो अन्य कार्यक्रमों द्वारा सहेजे जाते हैं जो लाइन ब्रेक के लिए एक अलग विधि का उपयोग करते हैं। यह अच्छी तरह से काम करता है यदि आप हर बार जानते हैं कि फ़ाइल हमेशा आपके वर्तमान ओएस के लाइन ब्रेक का उपयोग कर रही है।
क्रांग प्राइम

तो मैं जो सुन रहा हूं वह सबसे पठनीय तरीका है (शायद उच्चतर स्मृति उपयोग) foo = foo.Replace("\r\n", "\n"); string[] result = foo.Split('\n');। क्या मैं सही ढंग से समझ रहा हूं कि यह सभी प्लेटफार्मों पर काम करता है?
जॉन डो

4

मैं वर्तमान में VB.NET में इस फ़ंक्शन (अन्य उत्तरों के आधार पर) का उपयोग कर रहा हूं:

Private Shared Function SplitLines(text As String) As String()
    Return text.Split({Environment.NewLine, vbCrLf, vbLf}, StringSplitOptions.None)
End Function

यह पहले प्लेटफॉर्म-लोकल न्यूलाइन पर विभाजित होने की कोशिश करता है, और फिर प्रत्येक संभावित न्यूलाइन पर वापस आ जाता है।

मुझे केवल एक वर्ग के अंदर ही इसकी आवश्यकता है। यदि वह बदल जाता है, तो मैं शायद Publicइसे बनाऊंगा और इसे एक उपयोगिता वर्ग में स्थानांतरित करूंगा , और शायद इसे एक विस्तार विधि भी बनाऊं।

अच्छे उपाय के लिए यहाँ लाइनों को कैसे जोड़ा जाए:

Private Shared Function JoinLines(lines As IEnumerable(Of String)) As String
    Return String.Join(Environment.NewLine, lines)
End Function

@ शमूएल - उद्धरणों पर ध्यान दें। उनका वास्तव में यही अर्थ है। "\r"= लौट आया। "\r\n"= वापसी + नई लाइन। (कृपया इस पोस्ट और यहां स्वीकृत समाधान
क्रैंग प्राइम

@ क्रंग हम्म .. मैंने लंबे समय में .NET के साथ काम नहीं किया है। मुझे आश्चर्य होगा कि यदि बहुत से लोगों ने गलत उत्तर दिया। मुझे लगता है कि मैंने गुफ़ा के जवाब पर भी टिप्पणी की, और वहां स्पष्टीकरण मिला। मैंने इस उत्तर के लिए अपनी टिप्पणी हटा दी है। सर उठाने के लिए धन्यवाद।
शमूएल

2

ठीक है, वास्तव में विभाजन करना चाहिए:

//Constructing string...
StringBuilder sb = new StringBuilder();
sb.AppendLine("first line");
sb.AppendLine("second line");
sb.AppendLine("third line");
string s = sb.ToString();
Console.WriteLine(s);

//Splitting multiline string into separate lines
string[] splitted = s.Split(new string[] {System.Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries);

// Output (separate lines)
for( int i = 0; i < splitted.Count(); i++ )
{
    Console.WriteLine("{0}: {1}", i, splitted[i]);
}

2
RemoveEmptyEntries विकल्प पाठ से खाली लाइनों को हटा देगा। यह कुछ स्थितियों में वांछनीय हो सकता है, लेकिन एक सादे विभाजन को खाली लाइनों को संरक्षित करना चाहिए।
गुफ्फा

हाँ, आप सही कह रहे हैं, मैंने अभी यह धारणा बनाई है, कि ... अच्छी तरह से, खाली लाइनें दिलचस्प नहीं हैं;)
मैकियाक्लास्का

1
string[] lines = text.Split(
  Environment.NewLine.ToCharArray(), 
  StringSplitOptions.RemoveEmptyStrings);

RemoveEmptyStrings विकल्प सुनिश्चित करें कि आप \ N के कारण खाली प्रविष्टियों एक \ r निम्नलिखित की जरूरत नहीं है कर देगा

(टिप्पणियों को प्रतिबिंबित करने के लिए संपादित करें :) ध्यान दें कि यह पाठ में वास्तविक खाली लाइनों को भी त्याग देगा। यह आमतौर पर मैं क्या चाहता हूं, लेकिन यह आपकी आवश्यकता नहीं हो सकती है।


RemoveEmptyStrings विकल्प खाली लाइनों को भी हटा देगा, इसलिए यह ठीक से काम नहीं करता है यदि पाठ में खाली लाइनें हैं।
गुफ़ा

आप शायद वास्तविक खाली लाइनों को संरक्षित करना चाहते हैं: \ r \ n \ r \ n
पतला

0

मैं एनवायरनमेंट के बारे में नहीं जानता था। न्यूलाइन, लेकिन मुझे लगता है कि यह एक बहुत अच्छा समाधान है।

मेरी कोशिश होती:

        string str = "Test Me\r\nTest Me\nTest Me";
        var splitted = str.Split('\n').Select(s => s.Trim()).ToArray();

अतिरिक्त .Trim किसी भी \ r या \ n को हटाता है जो अभी भी मौजूद हो सकता है (उदाहरण के लिए जब विंडोज़ पर, लेकिन OS x newline वर्णों के साथ एक स्ट्रिंग को विभाजित करते हुए)। शायद सबसे तेज़ तरीका नहीं है।

संपादित करें:

जैसा कि टिप्पणियों ने सही ढंग से बताया है, यह लाइन की शुरुआत में या नई लाइन फीड से पहले किसी भी व्हाट्सएप को हटा देता है। यदि आपको उस व्हाट्सएप को संरक्षित करने की आवश्यकता है, तो अन्य विकल्पों में से एक का उपयोग करें।


ट्रिम लाइनों की शुरुआत और अंत में किसी भी सफेद स्थान को हटा देगा, उदाहरण के लिए इंडेंटेशन।
गुफा

".Trim किसी भी \ r या \ n को हटाता है जो अभी भी मौजूद हो सकता है" - ouch। इसके बजाय मजबूत कोड क्यों नहीं लिखें?
bzlm

शायद मुझे सवाल गलत लगा, लेकिन यह स्पष्ट नहीं था कि व्हाट्सएप को संरक्षित किया जाना चाहिए। बेशक आप सही हैं, ट्रिम () भी व्हाट्सएप को हटा देता है।
मैक्स

1
@Max:;) वाह, जब तक मैं अपने मालिक बता कोड कुछ भी है कि है विशेष रूप से विवरण में से इंकार नहीं करने की अनुमति दी जाती है कि ... इंतजार
Guffa

-2

मूर्खतापूर्ण उत्तर: एक अस्थायी फ़ाइल पर लिखें ताकि आप आदरणीय का उपयोग कर सकें File.ReadLines

var s = "Hello\r\nWorld";
var path = Path.GetTempFileName();
using (var writer = new StreamWriter(path))
{
    writer.Write(s);
}
var lines = File.ReadLines(path);

1
बचें var, क्योंकि यह चर के प्रकार को परिभाषित नहीं करता है, इसलिए आप यह नहीं समझ सकते कि उस वस्तु का उपयोग कैसे किया जाए, या वह वस्तु क्या दर्शाती है। इसके अलावा, यह लाइनें लिखना दिखाता है और फ़ाइल नाम भी निर्दिष्ट नहीं करता है, इसलिए मुझे संदेह है कि यह काम करेगा। फिर, पढ़ते समय, फ़ाइल का पथ फिर से निर्दिष्ट नहीं किया जाता है। यह मानते हुए कि pathहै C:\Temp\test.txt, आप तो होना चाहिए string[] lines = File.ReadLines(path);
vapcguy

1
@vapcguy मैंने अभी क्या पढ़ा है? - मैं पोस्ट को फिर से पढ़ने या इसे कंसोल प्रोग्राम में डीबग करने की सलाह दूंगा क्योंकि आपने जो कुछ भी कहा है वह सादा गलत है पथ Path.GetTempFileName पर सेट किया गया है var C # में एक सामान्य और अनुशंसित परिभाषा है - वैसे यह एक चर के प्रकार को परिभाषित करता है ...... EDIT: मैं यह नहीं कहता कि यह एक अच्छा समाधान है
koanbock

@koanbock ठीक है, तो मैंने देखा Path.GetTempFileName msdn.microsoft.com/en-us/library/… और यह कहता है कि यह एक शून्य-बाइट फ़ाइल बनाता है और "उस फ़ाइल का पूर्ण पथ" देता है। मैं शपथ ले सकता था कि मैंने पहले यह कोशिश की थी और इसने एक अपवाद दिया क्योंकि यह एक फ़ाइल नहीं मिला, लेकिन इसके बजाय एक फ़ोल्डर स्थान वापस कर दिया गया था। मैं उपयोग करने के लिए तर्क जानता हूं var, लेकिन मैं कहूंगा कि इसकी अनुशंसा नहीं की गई है क्योंकि यह नहीं दिखाता है कि चर वस्तु क्या है। यह उसे बाधित करता है।
vapcguy

-3
using System.IO;

string textToSplit;

if (textToSplit != null)
{
    List<string> lines = new List<string>();
    using (StringReader reader = new StringReader(textToSplit))
    {
        for (string line = reader.ReadLine(); line != null; line = reader.ReadLine())
        {
            lines.Add(line);
        }
    }
}

-5

बहुत आसान है, वास्तव में।

VB.NET:

Private Function SplitOnNewLine(input as String) As String
    Return input.Split(Environment.NewLine)
End Function

सी#:

string splitOnNewLine(string input)
{
    return input.split(environment.newline);
}

4
पूरी तरह से गलत है और काम नहीं करता है। साथ ही, C # में, यह Environment.NewLineVB की तरह ही है।
vapcguy

VB.NET में एंड-ऑफ-लाइन पहचानकर्ता देखें ? नई लाइन के लिए विभिन्न विकल्पों के लिए।
पीटर मोर्टेंसन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.