.NET स्ट्रिंग की अधिकतम संभव लंबाई क्या है?


239

.NET में बनाई जा सकने वाली सबसे लंबी स्ट्रिंग क्या है? Stringकक्षा के लिए डॉक्स इस सवाल पर चुप हैं, जहां तक ​​मैं देख सकता हूं, इसलिए एक आधिकारिक जवाब में इंटर्नल के कुछ ज्ञान की आवश्यकता हो सकती है। क्या 64-बिट सिस्टम पर अधिकतम परिवर्तन होगा?

[यह व्यावहारिक उपयोग की तुलना में जिज्ञासा के लिए अधिक पूछा जाता है - मैं किसी भी कोड को बनाने का इरादा नहीं करता जो विशाल तारों का उपयोग करता है!]

जवाबों:


346

सैद्धांतिक सीमा 2,147,483,647 हो सकती है, लेकिन व्यावहारिक सीमा कहीं नहीं है। चूंकि .NET प्रोग्राम में कोई भी ऑब्जेक्ट 2GB से अधिक नहीं हो सकता है और स्ट्रिंग प्रकार UTF-16 (प्रत्येक वर्ण के लिए 2 बाइट्स) का उपयोग करता है, सबसे अच्छा आप कर सकते हैं 1,073,741,823, लेकिन आप कभी भी इसे आवंटित करने में सक्षम होने की संभावना नहीं रखते हैं 32-बिट मशीन पर।

यह उन स्थितियों में से एक है जहां "यदि आपको पूछना है, तो आप शायद कुछ गलत कर रहे हैं।"


8
यह सही जवाब है। स्ट्रिंग लंबाई को समाप्त करने के लिए पर्याप्त आवंटित करने में सक्षम होने से पहले आपको मेमोरी से बाहर चलाने की अधिक संभावना है। एक ताजा बूट पर आप यहां बताए अनुसार 2GB (1M वर्णों के साथ) का आवंटन खींचने में सक्षम हो सकते हैं, लेकिन यह सब है।
स्टीफन डीकेन

4
यह मानते हुए कि आपकी "कोई भी एकल वस्तु 2Gb से अधिक नहीं हो सकती है" जोर सटीक है, यह सैद्धांतिक सीमा के साथ-साथ व्यावहारिक भी है - स्ट्रिंग की लंबाई पर अवरोध कुल वस्तु का आकार होगा, लंबाई क्षेत्र की क्षमता नहीं।
मैकेंजी 1

12
अगर किसी को सटीक मूल्य में दिलचस्पी है, तो मेरे 64-बिट मशीन पर 1,073,741,791 (1024 · 1024 · 1024 - 33) अक्षर हैं। सटीक अधिकतम आकार के बारे में मेरा संबंधित प्रश्नbyte[] भी देखें ।
svick

4
मैं उन उत्तरों के बारे में पागल हो जाता हूं जिनमें संक्षिप्त लेकिन गहराई से व्याख्या होती है।
मिकाईल अब्दुल्लायेव

3
.NET 4.5 (और बाद में) ऑब्जेक्ट को 64-बिट मशीनों पर 2GB से बड़ा होने की अनुमति देने का विकल्प है। यहां देखें
एंडरसन माटोस

72

मेरे अत्यधिक वैज्ञानिक और सटीक प्रयोग के आधार पर, यह 1,000,000,000 वर्णों से पहले मेरी मशीन में सबसे ऊपर है। (मैं अभी भी बेहतर पिनपॉइंट प्राप्त करने के लिए नीचे दिए गए कोड को चला रहा हूं)।

अद्यतन: कुछ घंटों के बाद, मैंने छोड़ दिया है। अंतिम परिणाम: 100,000,000 वर्णों की तुलना में बहुत बड़ा हो सकता है, तुरंत System.OutOfMemoryException1,000,000,000 वर्णों पर दिया जा सकता है ।

using System;
using System.Collections.Generic;

public class MyClass
{
    public static void Main()
    {
        int i = 100000000;
        try
        {
            for (i = i; i <= int.MaxValue; i += 5000)
            {
                string value = new string('x', i);
                //WL(i);
            }
        }
        catch (Exception exc)
        {
            WL(i);
            WL(exc);
        }
        WL(i);
        RL();
    }

    #region Helper methods

    private static void WL(object text, params object[] args)
    {
        Console.WriteLine(text.ToString(), args);   
    }

    private static void RL()
    {
        Console.ReadLine(); 
    }

    private static void Break() 
    {
        System.Diagnostics.Debugger.Break();
    }

    #endregion
}

35
यहाँ एक द्विआधारी खोज को लागू करने से शायद आपको यह उत्तर बहुत जल्दी मिल सके ...
मारियो

49

चूंकि Lengthसंपत्ति System.Stringएक है Int32, इसलिए मैं अनुमान लगाऊंगा कि अधिकतम लंबाई 2,147,483,647 चार्ट (अधिकतम Int32आकार) होगी। यदि यह लंबे समय तक अनुमति देता है तो आप लंबाई की जांच नहीं कर सकते क्योंकि यह विफल हो जाएगा।


2
@ m.edmondson: मैं वास्तव में आश्वस्त नहीं हूं। उदाहरणों के लिए एक सरणी के LongLengthरूप में एक अच्छी तरह से है और एक धारा longलंबाई के रूप में उपयोग करता है । यद्यपि यह मान्य उत्तर है, यह इसे मापने का एक सटीक तरीका है।
विलेम वैन ओन्सेम

1
लेकिन पहले दो बिट्स ASCII / गैर-ASCII संकेत के लिए उपयोग किए जाते हैं क्योंकि यह लेख कहता है, इसलिए यह 2 ^ 30 = 1 073 741 824 होना चाहिए
Saito

28

किसी को भी इस विषय पर देर से आने के लिए, मैं देख सकता था कि हिटस्कैन का "आपको शायद ऐसा नहीं करना चाहिए" किसी को यह पूछने का कारण बन सकता है कि उन्हें क्या चाहिए ...

StringBuilder वर्ग अक्सर एक आसान प्रतिस्थापन है। स्ट्रीम-आधारित कक्षाओं में से एक पर विशेष रूप से विचार करें , यदि आपका डेटा किसी फ़ाइल से आ रहा है।

इसके साथ समस्या s += "stuff"यह है कि इसे डेटा रखने के लिए एक पूरी तरह से नया क्षेत्र आवंटित करना है और फिर पुराने डेटा की सभी को कॉपी करना है और साथ ही नए सामान - EACH और EVERY LOOP ITERATION। तो, पाँच बाइट्स को 1,000,000 से जोड़ना s += "stuff"बेहद महंगा है। यदि आप चाहते हैं कि अंत में केवल पांच बाइट्स लिखना है और अपने कार्यक्रम के साथ आगे बढ़ना है, तो आपको एक वर्ग चुनना होगा जो कुछ कारकों को छोड़ देता है:

StringBuilder sb = new StringBuilder(5000);
for (; ; )
    {
        sb.Append("stuff");
    }

StringBuilderसीमा के बढ़ने पर ऑटो-ग्रोथ दोगुना हो जाएगा । इसलिए, आप शुरू में एक बार विकास दर्द देखेंगे, एक बार 5,000 बाइट्स पर, फिर से 10,000 पर, फिर से 20,000 पर। तार लगाने से दर्द हर पाश पुनरावृत्ति होगा।


4
यह भी ध्यान देने योग्य है कि स्ट्रिंगब्यूलर आपको शुरुआती आकार निर्धारित करने की अनुमति देता है। उपयोगी यदि आप जानते हैं कि आप समय से पहले 10,000,000 प्रविष्टियों का उपयोग करने जा रहे हैं, तो आपको कुछ क्रंच को अनदेखा करने की अनुमति मिलेगी।
काइल बरन

3
+1 प्रश्न के माध्यम से देखने और अच्छे डिज़ाइन के उत्तर देने के लिए। तुलनात्मक रूप से, "यह आपके धमाके से पहले कितना बड़ा तार हो सकता है", के विपरीत, "अगर आपको वास्तव में बहुत सारे पाठ को संग्रहीत करने की आवश्यकता है, तो इसका उपयोग करें ..."
StevoInco

8

एक स्ट्रिंग की अधिकतम लंबाई मेरी मशीन पर है +१०७३७४१७९१

आप देखते हैं, स्ट्रिंग्स पूर्णांक द्वारा सीमित नहीं हैं जैसा कि आमतौर पर माना जाता है।

मेमोरी प्रतिबंध अलग, स्ट्रिंग्स 2 30 ( 1,073,741,824) से अधिक नहीं हो सकते ) अक्षर , क्योंकि 2 जीबी की सीमा Microsoft सीएलआर (सामान्य भाषा रनटाइम) द्वारा लगाई जाती है। मेरे कंप्यूटर से 33 अधिक अनुमति दी।

अब, यहाँ कुछ है जिसका आप स्वयं प्रयास करने के लिए स्वागत करते हैं।

Visual Studio में एक नया C # कंसोल ऐप बनाएँ और फिर यहाँ मुख्य विधि को कॉपी / पेस्ट करें:

static void Main(string[] args)
{
    Console.WriteLine("String test, by Nicholas John Joseph Taylor");

    Console.WriteLine("\nTheoretically, C# should support a string of int.MaxValue, but we run out of memory before then.");

    Console.WriteLine("\nThis is a quickish test to narrow down results to find the max supported length of a string.");

    Console.WriteLine("\nThe test starts ...now:\n");

    int Length = 0;

    string s = "";

    int Increment = 1000000000; // We know that s string with the length of 1000000000 causes an out of memory exception.

    LoopPoint:

    // Make a string appendage the length of the value of Increment

    StringBuilder StringAppendage = new StringBuilder();

    for (int CharacterPosition = 0; CharacterPosition < Increment; CharacterPosition++)
    {
        StringAppendage.Append("0");

    }

    // Repeatedly append string appendage until an out of memory exception is thrown.

    try
    {
        if (Increment > 0)
            while (Length < int.MaxValue)
            {
                Length += Increment;

                s += StringAppendage.ToString(); // Append string appendage the length of the value of Increment

                Console.WriteLine("s.Length = " + s.Length + " at " + DateTime.Now.ToString("dd/MM/yyyy HH:mm"));

            }

    }
    catch (OutOfMemoryException ex) // Note: Any other exception will crash the program.
    {
        Console.WriteLine("\n" + ex.Message + " at " + DateTime.Now.ToString("dd/MM/yyyy HH:mm") + ".");

        Length -= Increment;

        Increment /= 10;

        Console.WriteLine("After decimation, the value of Increment is " + Increment + ".");

    }
    catch (Exception ex2)
    {
        Console.WriteLine("\n" + ex2.Message + " at " + DateTime.Now.ToString("dd/MM/yyyy HH:mm") + ".");

        Console.WriteLine("Press a key to continue...");

        Console.ReadKey();

    }

    if (Increment > 0)
    {
        goto LoopPoint;

    }

    Console.WriteLine("Test complete.");

    Console.WriteLine("\nThe max length of a string is " + s.Length + ".");

    Console.WriteLine("\nPress any key to continue.");

    Console.ReadKey();

}

मेरे परिणाम इस प्रकार थे:

स्ट्रिंग टेस्ट, निकोलस जॉन जोसेफ टेलर द्वारा

सैद्धांतिक रूप से, C # को int.MaxValue की एक स्ट्रिंग का समर्थन करना चाहिए, लेकिन हम तब से पहले मेमोरी से बाहर निकल जाते हैं।

यह एक स्ट्रिंग की अधिकतम समर्थित लंबाई का पता लगाने के लिए परिणामों को कम करने के लिए एक त्वरित परीक्षण है।

परीक्षण शुरू होता है ... अब:

s.Length = 1000000000 08/05/2019 12:06 पर

टंकित की छूट 'व्यवस्था। स्मृति के बाहर छूट' फेंका गया था। 08/05/2019 12:06 पर। विघटन के बाद, वृद्धि का मूल्य 100000000 है।

टंकित की छूट 'व्यवस्था। स्मृति के बाहर छूट' फेंका गया था। 08/05/2019 12:06 पर। विघटन के बाद, वेतन वृद्धि का मूल्य 10000000 है। s.Length = 1010000000 08/05/2019 12:06 s.Length = 1020000000 08/05/2019 12:06 s.Length = 1030000000 08/05/2019 12 बजे : 06 s.Length = 1040000000 बजे 08/05/2019 12:06 s.Length = 1050000000 08/05/2019 12:06 s.Length = 1060000000 08/05/2019 12:06 s.Length = 1070000000 बजे 08/05/2019 12:06

टंकित की छूट 'व्यवस्था। स्मृति के बाहर छूट' फेंका गया था। 08/05/2019 12:06 पर। निस्तारण के बाद, वृद्धि का मूल्य 1000000 है। s.Length = 1071000000 08/05/2019 12:06 s.Length = 1072000000 08/05/2019 12:06 s.Length = 1073000000 08/05/2019 12 बजे : 06

टंकित की छूट 'व्यवस्था। स्मृति के बाहर छूट' फेंका गया था। 08/05/2019 12:06 पर। विघटन के बाद, वेतन वृद्धि का मूल्य 100000 है। s.Length = 1073100000 08/05/2019 12:06 s.Length = 1073200000 08/05/2019 12:06 s.Length = 1073300000 पर 08/05/2019 12 : 06 s.Length = 1073400000 08/05/2019 12:06 s.Length = 1073500000 08/05/2019 12:06 s.Length = 1073600000 08/05/2019 12:06 s.Length = 1073700000 पर 08/05/2019 12:06

टंकित की छूट 'व्यवस्था। स्मृति के बाहर छूट' फेंका गया था। 08/05/2019 12:06 पर। निस्तारण के बाद, वृद्धि का मूल्य 10000 है। 08/05/2019 को 12। : ०६ एस.लिफ्टर = १०.L३400४००००० बजे ० s/०५/२०१२ १२:०६

टंकित की छूट 'व्यवस्था। स्मृति के बाहर छूट' फेंका गया था। 08/05/2019 12:06 पर। विघटन के बाद, वेतन वृद्धि का मूल्य 1000 है। sength = 1073741000 08/05/2019 12:06 पर

टंकित की छूट 'व्यवस्था। स्मृति के बाहर छूट' फेंका गया था। 08/05/2019 12:06 पर। विघटन के बाद, वृद्धि का मूल्य 100. sength है। 107/054 0800 08/05/2019 12:06 s.Length = 1073741200 08/05/2019 12:06 s.Length = 1073741300 08:00/2019 12 पर : 07 s.Length = 1073741400 08/05/2019 12:07 s.Length = 1073741500 पर 08/05/2019 12:07 s.Length = 1073741600 08/05/2019 12:07 s.Length = 1073741700 पर 08/05/2019 12:07

टंकित की छूट 'व्यवस्था। स्मृति के बाहर छूट' फेंका गया था। 08/05/2019 12:07 पर। विघटन के बाद, वृद्धि का मान 10./05 है। 107/0541710 08/05/2019 12:07 s.Length = 1073741720 08/05/2019 12:07 s.Length = 1073741730 08:00/2019 12 बजे : 07 s.Length = 1073741740 08/05/2019 12:07 s.Length = 1073741750 पर 08/05/2019 12:07 s.Length = 1073741760 08/05/2019 12:07 s.Length = 1073741770 पर 08/05/2019 12:07 s.Length = 1073741780 08/05/2019 12:07 s.Length = 1073741790 08/05/2019 12:07 पर

टंकित की छूट 'व्यवस्था। स्मृति के बाहर छूट' फेंका गया था। 08/05/2019 12:07 पर। विघटन के बाद, वृद्धि का मूल्य १.५.२६.०१ ९ १२:०६ पर १.५.२६५ = १०4३17४१ at ९ १ है

टंकित की छूट 'व्यवस्था। स्मृति के बाहर छूट' फेंका गया था। 08/05/2019 12:07 पर। विघटन के बाद, वृद्धि का मान 0. परीक्षण पूर्ण है।

एक स्ट्रिंग की अधिकतम लंबाई 1073741791 है।

जारी रखने के लिए किसी भी कुंजी को दबाएं।

मेरी मशीन पर एक स्ट्रिंग की अधिकतम लंबाई 1073741791 है।

अगर लोग नीचे एक टिप्पणी के रूप में अपने परिणाम पोस्ट कर सकते हैं तो मैं इसकी बहुत सराहना करूंगा।

यह सीखना दिलचस्प होगा कि क्या लोगों को समान या अलग-अलग परिणाम मिलते हैं।


"आप देखते हैं, स्ट्रिंग्स को पूर्णांक द्वारा सीमित नहीं किया जाता है जैसा कि आमतौर पर माना जाता है।" -> c # में एक पूर्णांक 2,147,483,647 तक जा सकता है और आपका परिणाम दो से विभाजित इस मान के बहुत करीब (32 बाइट्स कम) है, जो तर्कसंगत है क्योंकि एक स्ट्रिंग के प्रत्येक चरित्र को दो बाइट्स के रूप में यूनिकोड के रूप में संग्रहीत किया जाता है। तो भी अगर सीमा पूर्णांक के आकार द्वारा लागू नहीं की जाती है, तो यह उल्लेखनीय रूप से इसके करीब है।
बेन

2

200 megs ... जिस बिंदु पर आपका ऐप वर्चुअल हॉल्ट को पीसता है, उसमें एक गिग वर्किंग सेट मेमोरी होती है, और ओ / एस ऐसे कार्य करने लगता है, जैसे आपको रिबूट करने की आवश्यकता होगी।

static void Main(string[] args)
{
    string s = "hello world";
    for(;;)
    {
        s = s + s.Substring(0, s.Length/10);
        Console.WriteLine(s.Length);
    }
}

12
13
14
15
16
17
18
...
158905664
174796230
192275853
211503438

5
मुझे यकीन नहीं है कि जिस व्यवहार को आप वास्तव में बड़ा स्ट्रिंग बनाने से प्राप्त करेंगे, वह वही है जो आप देख रहे हैं कि उनमें से एक गुच्छा आवंटित करके और समवर्ती हो।
केसी

2

चूंकि String.Lengthएक पूर्णांक है (जो कि एक अन्य नाम है Int32), इसका आकार Int32.MaxValueयूनिकोड वर्णों तक सीमित है । ;-)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.