Was ist die maximal mögliche Länge einer .NET-Zeichenfolge?


239

Was ist die längste Zeichenfolge, die in .NET erstellt werden kann? StringSoweit ich sehen kann, schweigen die Dokumente für die Klasse zu dieser Frage, sodass für eine maßgebliche Antwort möglicherweise einige Kenntnisse der Interna erforderlich sind. Würde sich das Maximum auf einem 64-Bit-System ändern?

[Dies wird eher aus Neugier als aus praktischen Gründen verlangt - ich beabsichtige nicht, Code zu erstellen, der gigantische Zeichenfolgen verwendet!]

Antworten:


345

Die theoretische Grenze kann 2.147.483.647 betragen, aber die praktische Grenze liegt bei weitem nicht in der Nähe davon. Da kein einzelnes Objekt in einem .NET-Programm mehr als 2 GB groß sein darf und der Zeichenfolgentyp UTF-16 verwendet (2 Byte für jedes Zeichen), können Sie am besten 1.073.741.823 verwenden, aber Sie werden dies wahrscheinlich nie zuordnen können auf einem 32-Bit-Computer.

Dies ist eine dieser Situationen, in denen "Wenn Sie fragen müssen, machen Sie wahrscheinlich etwas falsch."


8
Dies ist die richtige Antwort. Es ist wahrscheinlicher, dass Ihnen der Speicher ausgeht, bevor Sie genug zuweisen können, um die Zeichenfolgenlänge zu erschöpfen. Bei einem Neustart können Sie möglicherweise eine Zuweisung von 2 GB (mit 1 Million Zeichen) abrufen, wie hier erwähnt, aber das ist alles.
Stephen Deken

4
Unter der Annahme, dass Ihre Behauptung "Kein einzelnes Objekt darf mehr als 2 GB groß sein" korrekt ist, ist dies sowohl die theoretische als auch die praktische Grenze. Die Einschränkung für die Zeichenfolgenlänge ist die Gesamtobjektgröße und nicht die Kapazität des Felds Länge.
McKenzieG1

12
Wenn sich jemand für den genauen Wert interessiert, sind es auf meinem 64-Bit-Computer 1.073.741.791 (1024 · 1024 · 1024 - 33) Zeichen. Siehe auch meine verwandte Frage zur genauen maximalen Größe vonbyte[] .
Svick

4
Ich bin verrückt nach Antworten, die kurze, aber ausführliche Erklärungen enthalten.
Mikayil Abdullayev

3
Es besteht die Möglichkeit, dass .NET 4.5-Objekte (und höher) auf 64-Bit-Computern größer als 2 GB sind. Überprüfen Sie hier
Anderson Matos

72

Basierend auf meinem hochwissenschaftlichen und genauen Experiment wird es auf meinem Computer weit vor 1.000.000.000 Zeichen übertroffen. (Ich führe immer noch den folgenden Code aus, um einen besseren Punkt zu erhalten).

UPDATE: Nach ein paar Stunden habe ich aufgegeben. Endergebnisse: Kann viel größer als 100.000.000 Zeichen sein, sofort angegeben System.OutOfMemoryExceptionbei 1.000.000.000 Zeichen.

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
Das Anwenden einer binären Suche hier würde Ihnen wahrscheinlich helfen, diese Antwort viel schneller zu finden ...
Mario

49

Da die LengthEigenschaft von ein System.Stringist Int32, würde ich vermuten, dass die maximale Länge 2.147.483.647 Zeichen (maximale Int32Größe) beträgt. Wenn es länger dauern würde, könnten Sie die Länge nicht überprüfen, da dies fehlschlagen würde.


2
@ m.edmondson: Ich bin eigentlich nicht überzeugt. Ein Array für Instanzen hat auch ein LongLengthund ein Stream verwendet longals Länge. Obwohl es eine gültige Antwort ist, ist es keine gute Möglichkeit, dies zu messen.
Willem Van Onsem

1
Aber die ersten beiden Bits werden für die ASCII / Nicht-ASCII-Anzeige verwendet, wie in diesem Artikel angegeben , daher sollte es 2 ^ 30 = 1 073 741 824
Saito

28

Für jeden, der spät zu diesem Thema kommt, könnte ich sehen, dass Hitscans "Sie sollten das wahrscheinlich nicht tun" jemanden dazu veranlassen könnte, zu fragen, was er tun soll ...

Die StringBuilder- Klasse ist häufig ein einfacher Ersatz. Betrachten Sie eine der Stream-basierten Klassen besonders dann, wenn Ihre Daten aus einer Datei stammen.

Das Problem dabei s += "stuff"ist, dass es einen völlig neuen Bereich für die Daten zuweisen und dann alle alten Daten sowie die neuen Daten kopieren muss - JEDE UND JEDE LOOP-ITERATION. Das Hinzufügen von fünf Bytes zu 1.000.000 mit s += "stuff"ist also äußerst kostspielig. Wenn Sie nur fünf Bytes bis zum Ende schreiben und mit Ihrem Programm fortfahren möchten, müssen Sie eine Klasse auswählen, die Raum für Wachstum lässt:

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

StringBuilderwird automatisch wachsen, indem es sich verdoppelt, wenn das Limit erreicht ist. Sie werden also den Wachstumsschmerz einmal zu Beginn sehen, einmal bei 5.000 Bytes, wieder bei 10.000, wieder bei 20.000. Das Anhängen von Zeichenfolgen verursacht bei jeder Schleifeniteration Schmerzen.


4
Es ist AUCH erwähnenswert, dass Sie mit StringBuilder die Anfangsgröße festlegen können. Nützlich, wenn Sie wissen, dass Sie im Voraus 10.000.000 Einträge verwenden werden, damit Sie einen Teil der Krise ignorieren können.
Kyle Baran

3
+1 Um die Frage zu durchschauen und auf gutes Design zu antworten. Vergleichsweise: "So groß kann Ihre Zeichenfolge sein, bevor sie durchbrennt", im Gegensatz zu "Wenn Sie WIRKLICH viel Text speichern müssen, verwenden Sie diese ..."
StevoInco

8

Die maximale Länge einer Zeichenfolge auf meinem Computer beträgt 1.073.741.791 .

Sie sehen, Strings sind nicht durch Ganzzahlen begrenzt, wie allgemein angenommen wird.

Abgesehen von Speicherbeschränkungen können Strings nicht mehr als 2 30 ( 1.073.741.824) haben ) Zeichen enthalten, da die Microsoft CLR (Common Language Runtime) eine Beschränkung von 2 GB . 33 mehr als mein Computer erlaubt.

Hier ist etwas, das Sie gerne selbst ausprobieren können.

Erstellen Sie eine neue C # -Konsolen-App in Visual Studio und kopieren Sie die Hauptmethode hier / fügen Sie sie ein:

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

}

Meine Ergebnisse waren wie folgt:

Stringtest von Nicholas John Joseph Taylor

Theoretisch sollte C # eine Zeichenfolge von int.MaxValue unterstützen, aber vorher geht uns der Speicher aus.

Dies ist ein schneller Test, um die Ergebnisse einzugrenzen und die maximal unterstützte Länge einer Zeichenfolge zu ermitteln.

Der Test beginnt ... jetzt:

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

Eine Fehlermeldung des Typs 'SystemOutOfMemoryException' wurde angezeigt. am 08/05/2019 12:06. Nach der Dezimierung beträgt der Wert von Increment 100000000.

Eine Fehlermeldung des Typs 'SystemOutOfMemoryException' wurde angezeigt. am 08/05/2019 12:06. Nach der Dezimierung beträgt der Wert für Inkrement 10000000. s.Length = 1010000000 am 08/05/2019 12:06 s.Length = 1020000000 am 08/05/2019 12:06 s.Length = 1030000000 am 08/05/2019 12 : 06 s.Length = 1040000000 am 08/05/2019 12:06 s.Length = 1050000000 am 08/05/2019 12:06 s.Length = 1060000000 am 08/05/2019 12:06 s.Length = 1070000000 at 08/05/2019 12:06

Eine Fehlermeldung des Typs 'SystemOutOfMemoryException' wurde angezeigt. am 08/05/2019 12:06. Nach der Dezimierung beträgt der Wert für Inkrement 1000000. s.Length = 1071000000 am 08/05/2019 12:06 s.Length = 1072000000 am 08/05/2019 12:06 s.Length = 1073000000 am 08/05/2019 12 : 06

Eine Fehlermeldung des Typs 'SystemOutOfMemoryException' wurde angezeigt. am 08/05/2019 12:06. Nach der Dezimierung beträgt der Wert von Inkrement 100000. s.Length = 1073100000 am 08/05/2019 12:06 s.Length = 1073200000 am 08/05/2019 12:06 s.Length = 1073300000 am 08/05/2019 12 : 06 s.Length = 1073400000 am 08/05/2019 12:06 s.Length = 1073500000 am 08/05/2019 12:06 s.Length = 1073600000 am 08/05/2019 12:06 s.Length = 1073700000 at 08/05/2019 12:06

Eine Fehlermeldung des Typs 'SystemOutOfMemoryException' wurde angezeigt. am 08/05/2019 12:06. Nach der Dezimierung beträgt der Wert für Inkrement 10000. s.Length = 1073710000 am 08/05/2019 12:06 s.Length = 1073720000 am 08/05/2019 12:06 s.Length = 1073730000 am 08/05/2019 12 : 06 s.Length = 1073740000 am 08/05/2019 12:06

Eine Fehlermeldung des Typs 'SystemOutOfMemoryException' wurde angezeigt. am 08/05/2019 12:06. Nach der Dezimierung beträgt der Wert von Inkrement 1000. s.Length = 1073741000 am 08/05/2019 12:06

Eine Fehlermeldung des Typs 'SystemOutOfMemoryException' wurde angezeigt. am 08/05/2019 12:06. Nach der Dezimierung beträgt der Wert für Inkrement 100. s.Length = 1073741100 am 08/05/2019 12:06 s.Length = 1073741200 am 08/05/2019 12:06 s.Length = 1073741300 am 08/05/2019 12 : 07 s.Length = 1073741400 am 08/05/2019 12:07 s.Length = 1073741500 am 08/05/2019 12:07 s.Length = 1073741600 am 08/05/2019 12:07 s.Length = 1073741700 at 08/05/2019 12:07

Eine Fehlermeldung des Typs 'SystemOutOfMemoryException' wurde angezeigt. am 08/05/2019 12:07. Nach der Dezimierung beträgt der Wert für Inkrement 10. s.Length = 1073741710 am 08/05/2019 12:07 s.Length = 1073741720 am 08/05/2019 12:07 s.Length = 1073741730 am 08/05/2019 12 : 07 s.Length = 1073741740 am 08/05/2019 12:07 s.Length = 1073741750 am 08/05/2019 12:07 s.Length = 1073741760 am 08/05/2019 12:07 s.Length = 1073741770 at 08/05/2019 12:07 s.Length = 1073741780 um 08/05/2019 12:07 s.Length = 1073741790 um 08/05/2019 12:07

Eine Fehlermeldung des Typs 'SystemOutOfMemoryException' wurde angezeigt. am 08/05/2019 12:07. Nach der Dezimierung beträgt der Wert von Inkrement 1. s.Length = 1073741791 am 08/05/2019 12:07

Eine Fehlermeldung des Typs 'SystemOutOfMemoryException' wurde angezeigt. am 08/05/2019 12:07. Nach der Dezimierung ist der Wert von Inkrement 0. Test abgeschlossen.

Die maximale Länge einer Zeichenfolge beträgt 1073741791.

Drücken Sie eine beliebige Taste, um fortzufahren.

Die maximale Länge eines Strings auf meinem Computer beträgt 1073741791.

Ich würde mich sehr freuen, wenn die Leute ihre Ergebnisse als Kommentar unten posten könnten.

Es wird interessant sein zu erfahren, ob Menschen die gleichen oder unterschiedliche Ergebnisse erzielen.


"Sie sehen, Strings sind nicht durch ganze Zahlen begrenzt, wie allgemein angenommen wird." -> Eine Ganzzahl in c # kann bis zu 2.147.483.647 betragen, und Ihr Ergebnis liegt sehr nahe (32 Byte weniger) an diesem durch zwei geteilten Wert, was logisch ist, da jedes Zeichen eines Strings als Unicode auf zwei Bytes gespeichert wird. Selbst wenn das Limit nicht durch die Größe der Ganzzahl vorgegeben ist, liegt es bemerkenswert nahe daran.
Ben

2

200 Megas ... an diesem Punkt kommt Ihre App zum virtuellen Stillstand, hat ungefähr einen Gig-Arbeitsset-Speicher und das Betriebssystem verhält sich so, als müssten Sie neu starten.

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
Ich bin mir nicht sicher, ob das Verhalten, das Sie beim Erstellen nur einer wirklich großen Zeichenfolge erhalten würden, das gleiche ist, das Sie sehen, wenn Sie eine Reihe von Zeichenfolgen zuweisen und verketten.
Casey

1

Da String.Lengthes sich um eine Ganzzahl handelt (dh um einen Alias ​​für Int32), ist ihre Größe auf Int32.MaxValueUnicode-Zeichen beschränkt. ;-);

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.