.NET字符串的最大可能长度是多少?


239

.NET中可以创建的最长字符串是什么?String据我所知,该类的文档对此问题保持沉默,因此权威的答案可能需要一些内部知识。在64位系统上最大的变化是吗?

[这是出于好奇而非实际用途的要求-我无意创建任何使用巨大字符串的代码!]

Answers:


346

理论极限可能是2,147,483,647,但实际极限还远远没有达到这个极限。由于.NET程序中的任何单个对象都不能超过2GB,并且字符串类型使用UTF-16(每个字符2个字节),因此您最好能做到1,073,741,823,但是您不可能分配在32位计算机上。

这是“如果必须提出要求,您可能做错了一些事情”的情况之一。


8
这是正确的答案。在分配足够的空间来耗尽字符串长度之前,您更有可能用完内存。如本文所述,您可以重新启动时分配2GB(带有1M个字符)的分配,仅此而已。
Stephen Deken

4
假设您的“任何单个对象都不能超过2Gb”断言是准确的,那么这既是理论上的限制,也是实际上的限制-字符串长度的约束将是对象的总大小,而不是“长度”字段的容量。
McKenzieG1

12
如果有人对确切的值感兴趣,在我的64位计算机上,它是1,073,741,791(1024·1024·1024-33)个字符。另请参阅有关的确切最大尺寸的相关问题byte[]
svick

4
我为包含简短但深入的解释的答案而疯狂。
Mikayil Abdullayev 2013年

3
有一个选项允许.NET 4.5(及更高版本)对象在64位计算机上大于2GB。在这里查看
Anderson Matos,2015年

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
在此处应用二进制搜索可能会帮助您更快地找到该答案……
Mario 2010年

49

由于的Length属性System.StringInt32,我猜最大长度为2,147,483,647个字符(最大Int32大小)。如果允许更长的时间,您将无法检查“长度”,因为那样会失败。


2
@ m.edmondson:我实际上并没有说服。实例的数组也有一个LongLength,流long用作长度。尽管这是正确的答案,但这并不是衡量此问题的准确方法。
Willem Van Onsem 2015年

1
但前两个比特用于ASCII /非ASCII指示如本文称,所以它应该是2 ^ 30 = 1 073 741 824
齐藤

28

对于迟到这个话题的任何人,我都能看到hitscan的“您可能不应该这样做”可能会引起某人问他们应该怎么做……

StringBuilder的类往往是一个易于更换。如果您的数据来自文件,则请考虑一种基于流的类

问题s += "stuff"在于它必须分配一个全新的区域来保存数据,然后将所有旧数据复制到其中,再加上新的内容-每个循环。因此,将5个字节加到1,000,000 s += "stuff"将非常昂贵。如果只想在末尾写入五个字节并继续执行程序,则必须选择一个有一定增长空间的类:

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

StringBuilder当达到极限时,将通过加倍自动增长。因此,您一开始就会看到增长的痛苦,一次是5,000字节,一次是10,000,再一次是20,000。追加字符串将在每次循环迭代时带来痛苦。


4
还值得注意的是,StringBuilder允许您设置初始大小。如果您知道将要提前使用10,000,000个条目,则很有用,从而可以忽略一些紧缩问题。
凯尔·巴兰

3
+1用于查看问题并回答良好的设计。相对而言,“这是您的字符串在吹起之前可以变大的大小”,而不是“如果您真的需要存储很多文本,请使用此...”
StevoInco 2015年

8

我的机器上字符串的最大长度为1,073,741,791

您会发现,字符串并不像通常认为的那样受整数限制。

除了内存限制,字符串不能超过2 301,073,741,824)个字符,因为Microsoft CLR(公共语言运行时)施加了2GB的限制。比我的电脑允许的数量多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字符串,但是在此之前我们用光了内存。

这是一项快速测试,可以缩小结果范围以找到字符串的最大支持长度。

测试开始...现在:

长度= 1000000000在08/05/2019 12:06

引发了类型为'System.OutOfMemoryException'的异常。在08/05/2019 12:06。抽取后,增量的值为100000000。

引发了类型为'System.OutOfMemoryException'的异常。在08/05/2019 12:06。抽取后,增量的值为10000000.s长度= 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 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/08/2019 12:06

引发了类型为'System.OutOfMemoryException'的异常。在08/05/2019 12:06。抽取后,增量的值为1000000.s的长度= 1071000000在08/05/2019 12:06 s.Length = 1072000000在08/05/2019 12:06 s.Length = 1073000000在08/05/2019 12 :06

引发了类型为'System.OutOfMemoryException'的异常。在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/08/2019 12:06

引发了类型为'System.OutOfMemoryException'的异常。在08/05/2019 12:06。抽取后,增量的值为10000.s.Length = 1073710000在08/05/2019 12:06 s.Length = 1073720000在08/05/2019 12:06 s.Length = 1073730000在08/05/2019 12 :06 s.Length = 1073740000 at 08/05/2019 12:06

引发了类型为'System.OutOfMemoryException'的异常。在08/05/2019 12:06。抽取后,Increment的值为1000。s.Length = 1073741000在08/05/2019 12:06

引发了类型为'System.OutOfMemoryException'的异常。在08/05/2019 12:06。抽取后,增量的值为100.s.Length = 1073741100在08/05/2019 12:06 s.Length = 1073741200在08/05/2019 12:06 s.Length = 1073741300在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.Length = 1073741700 at 08/05/2019 12:07

引发了类型为'System.OutOfMemoryException'的异常。在08/05/2019 12:07。抽取后,增量的值为10.s.Length = 1073741710在08/05/2019 12:07 s.Length = 1073741720在08/05/2019 12:07 s.Length = 1073741730在08/05/2019 12 :08 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.Length = 1073741770 at 08/05/2019 12:07 s.Length = 1073741780在08/05/2019 12:07 s.Length = 1073741790在08/05/2019 12:07

引发了类型为'System.OutOfMemoryException'的异常。在08/05/2019 12:07。抽取后,Increment的值为1. s.Length = 1073741791在08/05/2019 12:07

引发了类型为'System.OutOfMemoryException'的异常。在08/05/2019 12:07。抽取后,“增量”的值为0。测试完成。

字符串的最大长度是1073741791。

按任意键继续。

我的机器上字符串的最大长度为1073741791。

如果人们可以将其结果发表在下面的评论中,我将非常感激。

了解人们获得相同或不同结果的过程将很有趣。


“您知道,字符串不受通常认为的整数的限制。” -> c#中的整数最多可以达到2,147,483,647,结果与该值除以2的结果非常接近(减少了32个字节),这很合逻辑,因为String的每个字符都以Unicode的形式存储在两个字节上。因此,即使限制不是由整数的大小强加的,也非常接近它。

2

200兆...在这时,您的应用程序会陷入虚拟停顿,大约有演出工作集内存,并且操作系统开始表现为您需要重新启动。

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
我不确定通过仅创建一个很大的字符串所得到的行为是否与通过分配一堆字符串并进行串联所看到的行为相同。
Casey's

2

由于String.Length是整数(是的别名Int32),因此其大小限制为Int32.MaxValueunicode字符。;-)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.