Qual è la lunghezza massima possibile di una stringa .NET?


239

Qual è la stringa più lunga che può essere creata in .NET? I documenti per la Stringclasse sono in silenzio su questa domanda per quanto posso vedere, quindi una risposta autorevole potrebbe richiedere una certa conoscenza degli interni. Il cambiamento massimo su un sistema a 64 bit?

[Questo è richiesto più per curiosità che per un uso pratico - non intendo creare alcun codice che usi stringhe gigantesche!]

Risposte:


346

Il limite teorico può essere 2.147.483.647, ma il limite pratico non è affatto vicino a quello. Dato che nessun oggetto singolo in un programma .NET può superare i 2 GB e il tipo di stringa utilizza UTF-16 (2 byte per ogni carattere), il meglio che potresti fare è 1.073.741.823, ma non è probabile che tu sia in grado di allocare quello su una macchina a 32 bit.

Questa è una di quelle situazioni in cui "Se devi chiedere, probabilmente stai facendo qualcosa di sbagliato".


8
Questa è la risposta corretta È più probabile che rimanga a corto di memoria prima di essere in grado di allocare abbastanza per esaurire la lunghezza della stringa. Ad un nuovo avvio potresti essere in grado di ottenere un'allocazione di 2 GB (con caratteri 1M) come menzionato qui, ma questo è tutto.
Stephen Deken,

4
Supponendo che l'asserzione "nessun singolo oggetto può essere superiore a 2 GB" sia accurata, questo è il limite teorico e quello pratico - il vincolo sulla lunghezza della stringa sarebbe la dimensione totale dell'oggetto, non la capacità del campo Lunghezza.
McKenzieG1,

12
Se qualcuno è interessato al valore esatto, sulla mia macchina a 64 bit sono 1.073.741.791 (1024 · 1024 · 1024 - 33) caratteri. Vedi anche la mia domanda correlata sulla dimensione massima esatta dibyte[] .
svick,

4
Vado pazzo per le risposte che contengono spiegazioni brevi ma approfondite.
Mikayil Abdullayev il

3
Esiste un'opzione per consentire agli oggetti .NET 4.5 (e successivi) di essere più grandi di 2 GB su macchine a 64 bit. Controlla qui
Anderson Matos,

72

Basato sul mio esperimento altamente scientifico e accurato, supera la mia macchina ben prima di 1.000.000.000 di caratteri. (Sto ancora eseguendo il codice qui sotto per ottenere un punto più preciso).

AGGIORNAMENTO: Dopo alcune ore, ho rinunciato. Risultati finali: può andare molto più grande di 100.000.000 di caratteri, dato immediatamente System.OutOfMemoryExceptiona 1.000.000.000 di caratteri.

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
Applicare una ricerca binaria qui probabilmente ti aiuterà a trovare questa risposta molto più velocemente ...
Mario,

49

Poiché la Lengthproprietà di System.Stringè an Int32, immagino che la lunghezza massima sia di 2.147.483.647 caratteri ( Int32dimensione massima ). Se fosse consentito più a lungo, non è possibile controllare la lunghezza poiché ciò non riuscirebbe.


2
@ m.edmondson: in realtà non sono convinto. Un array per istanze ha LongLengthpure un e uno stream usa longcome lunghezza. Anche se è una risposta valida, è un modo accurato per misurarlo.
Willem Van Onsem,

1
Ma i primi due bit sono usati per l'indicazione ASCII / non ASCII come dice questo articolo , quindi dovrebbe essere 2 ^ 30 = 1 073 741 824
Saito

28

Per chiunque venisse in ritardo su questo argomento, ho potuto vedere che il hitcan "probabilmente non dovresti farlo" potrebbe indurre qualcuno a chiedere cosa dovrebbero fare ...

La classe StringBuilder è spesso una facile sostituzione. Considera una delle classi basate sul flusso in particolare, se i tuoi dati provengono da un file.

Il problema s += "stuff"è che deve allocare un'area completamente nuova per contenere i dati e quindi copiarvi tutti i vecchi dati più le nuove cose - OGNI E OGNI ITERAZIONE A LOOP. Quindi, aggiungere cinque byte a 1.000.000 con s += "stuff"è estremamente costoso. Se quello che vuoi è solo scrivere cinque byte fino alla fine e procedere con il tuo programma, devi scegliere una classe che lasci spazio alla crescita:

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

StringBuildercrescerà automaticamente raddoppiando quando viene raggiunto il limite. Quindi, vedrai il dolore della crescita una volta all'inizio, una volta a 5.000 byte, di nuovo a 10.000, di nuovo a 20.000. Le stringhe aggiunte comporteranno il dolore ad ogni iterazione del ciclo.


4
Vale anche la pena notare che StringBuilder consente di impostare la dimensione iniziale. Utile se sai che utilizzerai in anticipo 10.000.000 di voci, permettendoti di ignorare alcune delle crisi.
Kyle Baran,

3
+1 Per vedere attraverso la domanda e rispondere a un buon design. Comparativamente, "questo è quanto può essere grande la tua stringa prima che salti", al contrario di "se hai davvero bisogno di memorizzare un sacco di testo, usa questo ..."
StevoInco,

8

La lunghezza massima di una stringa sulla mia macchina è 1.073.741.791 .

Vedete, le stringhe non sono limitate dall'intero come si ritiene comunemente.

A parte le restrizioni di memoria, le stringhe non possono avere più di 2 30 ( 1.073.741.824 ) caratteri, poiché un limite di 2 GB è imposto dal CLR (Common Language Runtime). 33 in più del mio computer consentito.

Ora, ecco qualcosa che puoi provare tu stesso.

Crea una nuova app console C # in Visual Studio e copia / incolla qui il metodo principale:

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();

}

I miei risultati sono stati i seguenti:

Test delle corde, di Nicholas John Joseph Taylor

Teoricamente, C # dovrebbe supportare una stringa di int.MaxValue, ma prima di allora abbiamo esaurito la memoria.

Questo è un test rapido per restringere i risultati per trovare la lunghezza massima supportata di una stringa.

Il test inizia ... ora:

Lunghezza = 1000000000 all'08 / 05/2019 12:06

È stata generata un'eccezione di tipo "System.OutOfMemoryException". al 08/05/2019 12:06. Dopo la decimazione, il valore di Incremento è 100000000.

È stata generata un'eccezione di tipo "System.OutOfMemoryException". al 08/05/2019 12:06. Dopo la decimazione, il valore di Incremento è 10000000. s.Lunghezza = 1010000000 all'08 / 05/2019 12:06 s.Lunghezza = 1020000000 all'08 / 05/2019 12:06 s.Lunghezza = 1030000000 all'08 / 05/2019 12 : 06 s.Length = 1040000000 at 08/05/2019 12:06 s.Length = 1050000000 at 08/05/2019 12:06 s.Length = 1060000000 at 08/05/2019 12:06 s.Length = 1070000000 at 08/05/2019 12:06

È stata generata un'eccezione di tipo "System.OutOfMemoryException". al 08/05/2019 12:06. Dopo la decimazione, il valore di Incremento è 1000000. s.Lunghezza = 1071000000 all'08 / 05/2019 12:06 s.Lunghezza = 1072000000 all'08 / 05/2019 12:06 s.Lunghezza = 1073000000 all'08 / 05/2019 12 : 06

È stata generata un'eccezione di tipo "System.OutOfMemoryException". al 08/05/2019 12:06. Dopo la decimazione, il valore di Incremento è 100000. Lunghezza = 1073100000 al 08/05/2019 12:06 Lunghezza = 1073200000 al 08/05/2019 12:06 Lunghezza = 1073300000 al 08/05/2019 12 : 06 s.Length = 1073400000 at 08/05/2019 12:06 s.Length = 1073500000 at 08/05/2019 12:06 s.Length = 1073600000 at 08/05/2019 12:06 s.Length = 1073700000 at 08/05/2019 12:06

È stata generata un'eccezione di tipo "System.OutOfMemoryException". al 08/05/2019 12:06. Dopo la decimazione, il valore di Incremento è 10000. s.Lunghezza = 1073710000 al 08/05/2019 12:06 s.Lunghezza = 1073720000 al 08/05/2019 12:06 s.Lunghezza = 1073730000 al 08/05/2019 12 : 06 s.Lunghezza = 1073740000 al 08/05/2019 12:06

È stata generata un'eccezione di tipo "System.OutOfMemoryException". al 08/05/2019 12:06. Dopo la decimazione, il valore di Incremento è 1000. Lunghezza s = 1073741000 al 08/05/2019 12:06

È stata generata un'eccezione di tipo "System.OutOfMemoryException". al 08/05/2019 12:06. Dopo la decimazione, il valore di Incremento è 100. s.Lunghezza = 1073741100 all'08 / 05/2019 12:06 s.Lunghezza = 1073741200 all'08 / 05/2019 12:06 s.Lunghezza = 1073741300 all'08 / 05/2019 12 : 07 s.Length = 1073741400 at 08/05/2019 12:07 s.Length = 1073741500 at 08/05/2019 12:07 s.Length = 1073741600 at 08/05/2019 12:07 s.Lunghezza = 1073741700 at 08/05/2019 12:07

È stata generata un'eccezione di tipo "System.OutOfMemoryException". al 08/05/2019 12:07. Dopo la decimazione, il valore di Incremento è 10. s.Lunghezza = 1073741710 al 08/05/2019 12:07 s.Lunghezza = 1073741720 al 08/05/2019 12:07 s.Lunghezza = 1073741730 al 08/05/2019 12 : 07 s.Length = 1073741740 at 08/05/2019 12:07 s.Length = 1073741750 at 08/05/2019 12:07 s.Length = 1073741760 at 08/05/2019 12:07 s.Lunghezza = 1073741770 at 08/05/2019 12:07 s.Lunghezza = 1073741780 al 08/05/2019 12:07 s.Lunghezza = 1073741790 al 08/05/2019 12:07

È stata generata un'eccezione di tipo "System.OutOfMemoryException". al 08/05/2019 12:07. Dopo la decimazione, il valore di Incremento è 1. s.Lunghezza = 1073741791 al 08/05/2019 12:07

È stata generata un'eccezione di tipo "System.OutOfMemoryException". al 08/05/2019 12:07. Dopo la decimazione, il valore di Incremento è 0. Test completato.

La lunghezza massima di una stringa è 1073741791.

Premere un tasto qualsiasi per continuare.

La lunghezza massima di una stringa sulla mia macchina è 1073741791.

Apprezzerei molto se le persone potessero pubblicare i loro risultati come un commento qui sotto.

Sarà interessante sapere se le persone ottengono risultati uguali o diversi.


"Vedi, le stringhe non sono limitate dall'intero come si crede comunemente." -> un numero intero in c # può arrivare a 2.147.483.647 e il risultato è molto vicino (32 byte in meno) a questo valore diviso per due, il che è logico poiché ogni carattere di una stringa è memorizzato come Unicode su due byte. Quindi, anche se il limite non è imposto dalla dimensione dell'intero, è notevolmente vicino ad esso.
Ben

2

200 mega ... a quel punto la tua app si interrompe in modo virtuale, ha circa un concerto funzionante e la memoria inizia a funzionare come se dovessi riavviare.

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
Non sono sicuro che il comportamento che otterresti dalla creazione di una stringa davvero grande è lo stesso di quello che stai vedendo allocando un gruppo di essi e concatenandoli.
Casey,

2

Poiché String.Lengthè un numero intero (che è un alias per Int32), la sua dimensione è limitata ai Int32.MaxValuecaratteri unicode. ;-)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.