2015-12-23 10 views
7

मैंने स्ट्रिंग को विभाजित करने के लिए नीचे दिए गए कोड का उपयोग किया है, लेकिन इसमें काफी समय लगता है।छोटे टेक्स्ट को छोटे टुकड़ों में विभाजित करने का सबसे तेज़ तरीका

using (StreamReader srSegmentData = new StreamReader(fileNamePath)) 
{ 
    string strSegmentData = ""; 
    string line = srSegmentData.ReadToEnd(); 
    int startPos = 0; 

    ArrayList alSegments = new ArrayList(); 
    while (startPos < line.Length && (line.Length - startPos) >= segmentSize) 
    { 
     strSegmentData = strSegmentData + line.Substring(startPos, segmentSize) + Environment.NewLine; 
     alSegments.Add(line.Substring(startPos, segmentSize) + Environment.NewLine); 
     startPos = startPos + segmentSize; 
    } 
} 

कृपया मुझे तय आकार

+0

'String.S plit' एक विकल्प हो सकता है –

+0

इससे मदद मिल सकती है: http://stackoverflow.com/questions/568968/does-any-one-now-of-a-faster-method-to-do-string-split – MusicLovingIndianGirl

+0

हम डॉन ' स्प्लिट का उपयोग करने के लिए कोई विशिष्ट चरित्र नहीं है, बस आकार (वर्णों की संख्या) के आधार पर स्ट्रिंग को अलग करना होगा –

उत्तर

12

तुम सब परिभाषित करना चाहिए पहले के छोटे टुकड़ों में विभाजित करने के लिए स्ट्रिंग आप हिस्सा आकार साथ क्या मतलब है एक वैकल्पिक तरीका सुझाव देते हैं। यदि आपका भाग कोड इकाइयों की एक निश्चित संख्या के साथ है तो आपका वास्तविक एल्गोरिदम धीमा हो सकता है लेकिन यह काम करता है। यदि यह आपके इरादे से नहीं है और आप वास्तव में भाग वर्ण की निश्चित संख्या के साथ हैं तो यह टूट गया है। मैंने इस कोड समीक्षा पोस्ट में एक समान मुद्दे पर चर्चा की: Split a string into chunks of the same length तो मैं यहां केवल प्रासंगिक भागों को दोहरा दूंगा।

  1. एक चरित्र की तुलना में अधिक से एन्कोड किया गया है:

    • आप Char लेकिन String से अधिक विभाजन रहे UTF-16 इनकोडिंग तो, कम से कम, तीन मामलों आप टूट तार का उत्पादन हो सकता है एक कोड इकाई। उस चरित्र के लिए यूनिकोड कोड बिंदु दो यूटीएफ -16 कोड इकाइयों के रूप में एन्कोड किया गया है, प्रत्येक कोड इकाई दो अलग-अलग स्लाइसों में समाप्त हो सकती है (और दोनों तार अमान्य) होंगे।

    • एक चरित्र एक से अधिक कोड बिंदु द्वारा रचित है। आप दो अलग यूनिकोड कोड बिंदुओं (उदाहरण के लिए हान चरित्र) द्वारा बनाए गए चरित्र से निपट रहे हैं।
    • एक चरित्र में वर्ण या संशोधक संयोजन हैं। उदाहरण यूनिकोड की तरह U + 0300 चरित्र के संयोजन ग्रेव एक्सेंट à और यूनिकोड संशोधक ऐसे के रूप में U + 02BC संशोधक पत्र apostropheनिर्माणकरने के लिए इस्तेमाल के संयोजन के लिए: इस से आपको लगता है हो सकता है अधिक आम है।
  • एक प्रोग्रामिंग भाषा के लिए और एक आम इंसान चरित्र की परिभाषा स्लोवाक में उदाहरण के लिए, बहुत अलग हैं DZ एकल वर्ण लेकिन यह 2/3 यूनिकोड कोड अंक जो इस मामले में कर रहे हैं के द्वारा बनाई गई है 2/3 यूटीएफ -16 कोड इकाइयां तो "dž".Length > 1। इस और अन्य सांस्कृतिक मुद्दोंHow can I perform a Unicode aware character by character comparison? पर इसके बारे में अधिक जानकारी।
  • लिगरेचर मौजूद हैं। एक लिगरेचर मानना ​​एक कोड बिंदु है (और यह भी मानते हुए कि यह एक कोड इकाई के रूप में एन्कोड किया गया है) तो आप इसे एक ग्लाइफ के रूप में देखेंगे, हालांकि यह दो वर्ण का प्रतिनिधित्व करता है। इस मामले में क्या करना है? की सामान्य परिभाषा में वर्ण बहुत अस्पष्ट हो सकता है क्योंकि इस शब्द का उपयोग करने वाले अनुशासन के अनुसार अर्थ है। आप (शायद) सही ढंग से सब कुछ संभाल नहीं सकते हैं लेकिन आपको कुछ बाधाओं और दस्तावेज़ कोड व्यवहार को सेट करना चाहिए।
  • एक प्रस्तावित (और untested) कार्यान्वयन इस हो सकता है:

    public static IEnumerable<string> Split(this string value, int desiredLength) 
    { 
        var characters = StringInfo.GetTextElementEnumerator(value); 
        while (characters.MoveNext()) 
         yield return String.Concat(Take(characters, desiredLength)); 
    } 
    
    private static IEnumerable<string> Take(TextElementEnumerator enumerator, int count) 
    { 
        for (int i = 0; i < count; ++i) 
        { 
         yield return (string)enumerator.Current; 
    
         if (!enumerator.MoveNext()) 
          yield break; 
        } 
    } 
    

    यह गति के लिए अनुकूलित नहीं कर रहा है (जैसा कि आप देख सकते हैं मैं कोड कम रखने की कोशिश की और enumerations का उपयोग कर साफ़ करें) लेकिन, बड़ी फ़ाइलों के लिए , यह अभी भी आपके कार्यान्वयन से बेहतर प्रदर्शन करता है (कारण के लिए अगला पैराग्राफ देखें)।

    अपने कोड टिप्पणी के बारे में है कि:

    • आप एक विशाल ArrayList धारण करने के लिए परिणाम बना रहे हैं (?!)। यह भी ध्यान रखें कि इस तरह आप ArrayList कई बार आकार बदलते हैं (भले ही, इनपुट आकार और खंड आकार दिया गया हो, फिर भी इसका अंतिम आकार ज्ञात है)।
    • strSegmentData कई बार पुनर्निर्मित किया गया है, यदि आपको अक्षरों को जमा करने की आवश्यकता है तो आपको StringBuilder का उपयोग करना होगा अन्यथा प्रत्येक ऑपरेशन एक नई स्ट्रिंग आवंटित करेगा और पुराना मान कॉपी करेगा (यह धीमा है और यह कचरा कलेक्टर पर दबाव भी जोड़ता है)।

    तेजी से कार्यान्वयन कर रहे हैं (लिंक किए गए देख कोड की समीक्षा के बाद, विशेष रूप से एक बहुत तेजी से संस्करण के लिए Heslacher's implementation) और यदि आप सही ढंग से यूनिकोड को संभालने की जरूरत नहीं है (यदि आप यकीन आप केवल अमेरिका ASCII वर्ण का प्रबंधन कर रहे हैं) तो एक सुंदर readable implementation from Jon Skeet भी है (ध्यान दें कि, आपके कोड को प्रोफाइल करने के बाद, आप अभी भी सही आकार आउटपुट सूची को पूर्व-आवंटित करने वाली बड़ी फ़ाइलों के लिए अपना प्रदर्शन सुधार सकते हैं)। मैं यहां अपना कोड दोहराता हूं तो कृपया लिंक किए गए पदों का संदर्भ लें।

    अपने विशिष्ट आप स्मृति में पूरे विशाल फ़ाइल को पढ़ने की जरूरत नहीं है के लिए, आप पढ़ सकते हैं/n पात्रों को पार्स समय में (डिस्क का उपयोग के बारे में बहुत ज्यादा चिंता मत करो, मैं/हे बफ़र है)। यह प्रदर्शन को थोड़ा कम कर देगा लेकिन यह स्मृति उपयोग में काफी सुधार करेगा। वैकल्पिक रूप से आप लाइन से लाइन पढ़ सकते हैं (क्रॉस-लाइन भाग को संभालने के लिए प्रबंधन)।

    0

    नीचे, अपने प्रश्न और कोड के अपने विश्लेषण (टिप्पणी पढ़ने)

    using (StreamReader srSegmentData = new StreamReader(fileNamePath)) 
    { 
        string strSegmentData = ""; 
        string line = srSegmentData.ReadToEnd(); // Why are you reading this till the end if it is such a long string? 
        int startPos = 0; 
    
        ArrayList alSegments = new ArrayList(); // Better choice would be to use List<string> 
        while (startPos < line.Length && (line.Length - startPos) >= segmentSize) 
        { 
         strSegmentData = strSegmentData + line.Substring(startPos, segmentSize) + Environment.NewLine; // Seem like you are inserting linebreaks at specified interval in your original string. Is that what you want? 
         alSegments.Add(line.Substring(startPos, segmentSize) + Environment.NewLine); // Why are you recalculating the Substring? Why are you appending the newline if the aim is to just "split" 
         startPos = startPos + segmentSize; 
        } 
    } 
    

    धारणा सभी तरह बनाना है नीचे कोड मैं लंबी स्ट्रिंग विभाजित करने के लिए सिफारिश करेंगे है। नमूना में आप जो कर रहे हैं वह करने का यह एक साफ तरीका है। आप इसे अनुकूलित कर सकते हैं, लेकिन यह सुनिश्चित नहीं कर सकते कि आप कितनी तेजी से खोज रहे हैं।

    static void Main(string[] args) { 
        string fileNamePath = "ConsoleApplication1.pdb"; 
        var segmentSize = 32; 
    
        var op = ReadSplit(fileNamePath, segmentSize); 
        var joinedSTring = string.Join(Environment.NewLine, op); 
    } 
    
    static List<string> ReadSplit(string filePath, int segmentSize) { 
        var splitOutput = new List<string>(); 
        using (var file = new StreamReader(filePath, Encoding.UTF8, true, 8 * 1024)) { 
         char []buffer = new char[segmentSize]; 
         while (!file.EndOfStream) { 
          int n = file.ReadBlock(buffer, 0, segmentSize); 
          splitOutput.Add(new string(buffer, 0, n)); 
         } 
        } 
    
        return splitOutput; 
    } 
    

    मैंने अपने संस्करण पर कोई प्रदर्शन परीक्षण नहीं किया है, लेकिन मेरा अनुमान है कि यह आपके संस्करण से तेज़ है।

    इसके अलावा, मुझे यकीन नहीं है कि आप आउटपुट का उपभोग करने की योजना कैसे बनाते हैं, लेकिन I/O करते समय एक अच्छा अनुकूलन एसिंक कॉल का उपयोग करना है।और (पठनीयता और जटिलता की कीमत पर) एक अच्छा अनुकूलन जब बड़े से निपटने stringchar[]

    ध्यान दें कि

    • आप फ़ाइल
    • पढ़ते समय चरित्र एन्कोडिंग मुद्दों से निपटने के लिए हो सकता है के साथ रहना है आप पहले से ही स्मृति और फ़ाइल पढ़ने में लंबी स्ट्रिंग सिर्फ डेमो में शामिल किया गया था, तो आप StreamReader वर्ग के बजाय StringReader वर्ग का उपयोग करना चाहिए
    संबंधित मुद्दे