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

发布于 2024-07-05 21:00:25 字数 159 浏览 8 评论 0原文

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

[这更多的是出于好奇而不是实际用途 - 我不打算创建任何使用巨大字符串的代码!]

What is the longest string that can be created in .NET? The docs for the String class are silent on this question as far as I can see, so an authoritative answer might require some knowledge of internals. Would the maximum change on a 64-bit system?

[This is asked more for curiosity than for practical use - I don't intend to create any code that uses gigantic strings!]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

云柯 2024-07-12 21:00:25

理论限制可能是 2,147,483,647,但实际限制远非如此。 由于 .NET 程序中的单个对象可能不会超过 2GB,并且字符串类型使用 UTF-16(每个字符 2 个字节),因此您可以做的最好的事情是 1,073,741,823,但您不太可能能够分配它在 32 位机器上。

这是其中一种情况,“如果您必须问,您可能是做错事了。”

The theoretical limit may be 2,147,483,647, but the practical limit is nowhere near that. Since no single object in a .NET program may be over 2GB and the string type uses UTF-16 (2 bytes for each character), the best you could do is 1,073,741,823, but you're not likely to ever be able to allocate that on a 32-bit machine.

This is one of those situations where "If you have to ask, you're probably doing something wrong."

金橙橙 2024-07-12 21:00:25

根据我高度科学且准确的实验,它在我的机器上早在 1,000,000,000 个字符之前就达到了顶峰。 (我仍在运行下面的代码以获得更好的精确定位)。

更新:
几个小时后,我放弃了。 最终结果:可以超过 100,000,000 个字符,在 1,000,000,000 个字符时立即给出 System.OutOfMemoryException。

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
}

Based on my highly scientific and accurate experiment, it tops out on my machine well before 1,000,000,000 characters. (I'm still running the code below to get a better pinpoint).

UPDATE:
After a few hours, I've given up. Final results: Can go a lot bigger than 100,000,000 characters, instantly given System.OutOfMemoryException at 1,000,000,000 characters.

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
}
萌吟 2024-07-12 21:00:25

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

Since the Length property of System.String is an Int32, I would guess that that the maximum length would be 2,147,483,647 chars (max Int32 size). If it allowed longer you couldn't check the Length since that would fail.

暖风昔人 2024-07-12 21:00:25

对于迟到的人来说,我可以看到 hitscan 的“你可能不应该这样做”可能会导致有人问他们应该做什么......

StringBuilder 类通常很容易替换。
考虑基于流的类之一特别是,如果您的数据来自文件。

s += "stuff" 的问题在于它必须分配一个全新的区域来保存数据,然后将所有旧数据以及新数据复制到其中 - 每个循环迭代。 因此,使用 s += "stuff" 将 5 个字节添加到 1,000,000 的成本极其高昂。
如果您想要的只是在末尾写入五个字节并继续执行您的程序,则必须选择一个留有一些增长空间的类:

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

StringBuilder达到限制时加倍自动增长。 因此,您会在开始时看到一次增长的痛苦,一次在 5,000 字节,一次在 10,000 字节,再次在 20,000 字节。 每次循环迭代时附加字符串都会带来痛苦。

For anyone coming to this topic late, I could see that hitscan's "you probably shouldn't do that" might cause someone to ask what they should do…

The StringBuilder class is often an easy replacement.
Consider one of the stream-based classes especially, if your data is coming from a file.

The problem with s += "stuff" is that it has to allocate a completely new area to hold the data and then copy all of the old data to it plus the new stuff - EACH AND EVERY LOOP ITERATION. So, adding five bytes to 1,000,000 with s += "stuff" is extremely costly.
If what you want is to just write five bytes to the end and proceed with your program, you have to pick a class that leaves some room for growth:

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

StringBuilder will auto-grow by doubling when it's limit is hit. So, you will see the growth pain once at start, once at 5,000 bytes, again at 10,000, again at 20,000. Appending strings will incur the pain every loop iteration.

晚风撩人 2024-07-12 21:00:25

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

您会看到,字符串并不像人们普遍认为的那样受到整数的限制。

除了内存限制之外,字符串的长度不能超过 230 (1,073,741,824) 个字符,因为 Microsoft CLR(公共语言运行时)规定了 2GB 的限制。 超过我的计算机允许的 33 个。

现在,欢迎您亲自尝试一下。

在 Visual Studio 中创建一个新的 C# 控制台应用程序,然后将 main 方法复制/粘贴到此处:

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 at 08/05/2019 12:06

引发了“System.OutOfMemoryException”类型的异常。 在
2019 年 8 月 5 日 12:06。 抽取后,Increment 的值为
100000000。

引发了“System.OutOfMemoryException”类型的异常。 在
2019 年 8 月 5 日 12:06。 抽取后,Increment 的值为
10000000.s.Length = 1010000000 at 08/05/2019 12:06 s.Length = 1020000000 at 08/05/2019 12:06 s.Length = 1030000000 at 08/05/2019
12:06 秒.长度 = 1040000000 在 08/05/2019 12:06 秒.长度 = 1050000000
at 08/05/2019 12:06 s.Length = 1060000000 at 08/05/2019 12:06 s.Length
= 1070000000 于 08/05/2019 12:06

引发了“System.OutOfMemoryException”类型的异常。 在
2019 年 8 月 5 日 12:06。 抽取后,Increment 的值为 1000000。
s.Length = 1071000000 at 08/05/2019 12:06 s.Length = 1072000000 at
08/05/2019 12:06 s.长度 = 1073000000 at 08/05/2019 12:06

引发了“System.OutOfMemoryException”类型的异常。 在
2019 年 8 月 5 日 12:06。 抽取后,Increment 的值为 100000。
s.Length = 1073100000 at 08/05/2019 12:06 s.Length = 1073200000 at
08/05/2019 12:06 s.Length = 1073300000 在 08/05/2019 12:06 s.Length =
1073400000 at 08/05/2019 12:06 s.长度 = 1073500000 at 08/05/2019
12:06 秒.长度 = 1073600000 在 08/05/2019 12:06 秒.长度 = 1073700000
于 08/05/2019 12:06

引发了“System.OutOfMemoryException”类型的异常。 在
2019 年 8 月 5 日 12:06。 抽取后,Increment 的值为 10000。
s.Length = 1073710000 at 08/05/2019 12:06 s.Length = 1073720000 at
08/05/2019 12:06 s.Length = 1073730000 在 08/05/2019 12:06 s.Length =
1073740000 于 08/05/2019 12:06

引发了“System.OutOfMemoryException”类型的异常。 在
2019 年 8 月 5 日 12:06。 抽取后,Increment 的值为 1000。
s.Length = 1073741000 at 08/05/2019 12:06

引发了“System.OutOfMemoryException”类型的异常。 在
2019 年 8 月 5 日 12:06。 抽取后,Increment 的值为 100。
s.Length = 1073741100 at 08/05/2019 12:06 s.Length = 1073741200 at
08/05/2019 12:06 s.Length = 1073741300 在 08/05/2019 12:07 s.Length =
1073741400 at 08/05/2019 12:07 s.长度 = 1073741500 at 08/05/2019
12:07 s.Length = 1073741600 在 08/05/2019 12:07 s.Length = 1073741700
于 08/05/2019 12:07

引发了“System.OutOfMemoryException”类型的异常。 在
2019 年 8 月 5 日 12:07。 抽取后,Increment 的值为 10。
s.Length = 1073741710 at 08/05/2019 12:07 s.Length = 1073741720 at
08/05/2019 12:07 s.Length = 1073741730 在 08/05/2019 12:07 s.Length =
1073741740 at 08/05/2019 12:07 s.长度 = 1073741750 at 08/05/2019
12:07 s.Length = 1073741760 在 08/05/2019 12:07 s.Length = 1073741770
at 08/05/2019 12:07 s.Length = 1073741780 at 08/05/2019 12:07 s.Length
= 1073741790 于 08/05/2019 12:07

引发了“System.OutOfMemoryException”类型的异常。 在
2019 年 8 月 5 日 12:07。 抽取后,Increment 的值为 1。
s.Length = 1073741791 at 08/05/2019 12:07

引发了“System.OutOfMemoryException”类型的异常。 在
2019 年 8 月 5 日 12:07。 抽取后,Increment的值为0。 测试
完成。

字符串的最大长度为 1073741791。

按任意键继续。

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

如果人们可以将他们的结果作为评论发布在下面,我将非常感激。

了解人们是否得到相同或不同的结果将会很有趣。

The max length of a string on my machine is 1,073,741,791.

You see, Strings aren't limited by integer as is commonly believed.

Memory restrictions aside, Strings cannot have more than 230 (1,073,741,824) characters, since a 2GB limit is imposed by the Microsoft CLR (Common Language Runtime). 33 more than my computer allowed.

Now, here's something you're welcome to try yourself.

Create a new C# console app in Visual Studio and then copy/paste the main method here:

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

}

My results were as follows:

String test, by Nicholas John Joseph Taylor

Theoretically, C# should support a string of int.MaxValue, but we run
out of memory before then.

This is a quickish test to narrow down results to find the max
supported length of a string.

The test starts ...now:

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

Exception of type 'System.OutOfMemoryException' was thrown. at
08/05/2019 12:06. After decimation, the value of Increment is
100000000.

Exception of type 'System.OutOfMemoryException' was thrown. at
08/05/2019 12:06. After decimation, the value of Increment is
10000000. s.Length = 1010000000 at 08/05/2019 12:06 s.Length = 1020000000 at 08/05/2019 12:06 s.Length = 1030000000 at 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

Exception of type 'System.OutOfMemoryException' was thrown. at
08/05/2019 12:06. After decimation, the value of Increment is 1000000.
s.Length = 1071000000 at 08/05/2019 12:06 s.Length = 1072000000 at
08/05/2019 12:06 s.Length = 1073000000 at 08/05/2019 12:06

Exception of type 'System.OutOfMemoryException' was thrown. at
08/05/2019 12:06. After decimation, the value of Increment is 100000.
s.Length = 1073100000 at 08/05/2019 12:06 s.Length = 1073200000 at
08/05/2019 12:06 s.Length = 1073300000 at 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

Exception of type 'System.OutOfMemoryException' was thrown. at
08/05/2019 12:06. After decimation, the value of Increment is 10000.
s.Length = 1073710000 at 08/05/2019 12:06 s.Length = 1073720000 at
08/05/2019 12:06 s.Length = 1073730000 at 08/05/2019 12:06 s.Length =
1073740000 at 08/05/2019 12:06

Exception of type 'System.OutOfMemoryException' was thrown. at
08/05/2019 12:06. After decimation, the value of Increment is 1000.
s.Length = 1073741000 at 08/05/2019 12:06

Exception of type 'System.OutOfMemoryException' was thrown. at
08/05/2019 12:06. After decimation, the value of Increment is 100.
s.Length = 1073741100 at 08/05/2019 12:06 s.Length = 1073741200 at
08/05/2019 12:06 s.Length = 1073741300 at 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

Exception of type 'System.OutOfMemoryException' was thrown. at
08/05/2019 12:07. After decimation, the value of Increment is 10.
s.Length = 1073741710 at 08/05/2019 12:07 s.Length = 1073741720 at
08/05/2019 12:07 s.Length = 1073741730 at 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.Length = 1073741770
at 08/05/2019 12:07 s.Length = 1073741780 at 08/05/2019 12:07 s.Length
= 1073741790 at 08/05/2019 12:07

Exception of type 'System.OutOfMemoryException' was thrown. at
08/05/2019 12:07. After decimation, the value of Increment is 1.
s.Length = 1073741791 at 08/05/2019 12:07

Exception of type 'System.OutOfMemoryException' was thrown. at
08/05/2019 12:07. After decimation, the value of Increment is 0. Test
complete.

The max length of a string is 1073741791.

Press any key to continue.

The max length of a string on my machine is 1073741791.

I'd appreciate it very much if people could post their results as a comment below.

It will be interesting to learn if people get the same or different results.

蓝眼泪 2024-07-12 21:00:25

由于 String.Length 是一个整数(即 Int32 的别名),因此其大小仅限于 Int32.MaxValue unicode 字符。 ;-)

Since String.Length is an integer (that is an alias for Int32), its size is limited to Int32.MaxValue unicode characters. ;-)

提笔书几行 2024-07-12 21:00:25

字符串在 RAM 堆中分配动态内存大小。 但字符串地址存储在占用4字节内存的堆栈中。

String allocates dynamic memory size in the heap of your RAM. But string address is stored in stack that occupies 4 bytes of memory.

橘亓 2024-07-12 21:00:25

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

200 megs... at which point your app grinds to a virtual halt, has about a gig working set memory, and the o/s starts to act like you'll need to reboot.

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文