在.NET中能够创建的最长字符串是多少?就我所见,String
类的文档对此问题并没有提供明确的答案,因此权威答案可能需要一些内部知识。在64位系统上,最大值是否会发生变化?
[这更多是出于好奇而不是实际使用 - 我没有打算创建任何使用巨大字符串的代码!]
理论上的限制可能达到2,147,483,647,但实际限制远远没有那么高。由于.NET程序中没有单个对象可以超过2GB,并且字符串类型使用UTF-16(每个字符2个字节),因此您最多可以达到1,073,741,823个字符,但在32位机器上很难分配。
这是其中之一“如果您必须问,那么您可能正在做错什么”的情况。
根据我的高度科学和准确的实验,在我的机器上,它在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
}
s += "stuff"
的问题在于它必须分配一个完全新的区域来保存数据,然后将所有旧数据以及新数据复制到它上面 - 每次循环迭代都要这样做。因此,使用s += "stuff"
将五个字节添加到1,000,000个字节中非常昂贵。如果您想要的只是在末尾写入五个字节并继续进行程序,则必须选择一个留有一些增长空间的类:StringBuilder sb = new StringBuilder(5000);
for (; ; )
{
sb.Append("stuff");
}
StringBuilder
在达到其限制时会进行自动倍增。因此,您将在开始时看到一次增长痛苦,然后在5,000个字节处再次出现,然后在10,000和20,000处再次出现。每次循环迭代附加字符串都会产生这种痛苦。
在我的机器上,字符串的最大长度是1,073,741,791。
你看,与普遍认为的不同,字符串并不受整数的限制。
除了内存限制外,由于Microsoft CLR(公共语言运行时)实施了2GB限制,因此字符串不能超过230(1,073,741,824)个字符。比我的计算机少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 at 08/05/2019 12:06
在08/05/2019 12:06抛出了类型为“System.OutOfMemoryException”的异常。经过裁减,增量值为100000000。
在08/05/2019 12:06抛出了类型为“System.OutOfMemoryException”的异常。经过裁减,增量值为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抛出了类型为“System.OutOfMemoryException”的异常。经过裁减,增量值为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抛出了类型为“System.OutOfMemoryException”的异常。经过裁减,增量值为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抛出了类型为“System.OutOfMemoryException”的异常。经过裁减,增量值为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,时间为08/05/2019 12:06
在08/05/2019 12:06抛出了类型为“System.OutOfMemoryException”的异常。经过裁减,增量值为1000。s.Length = 1073741000,时间为08/05/2019 12:06
在08/05/2019 12:06抛出了类型为“System.OutOfMemoryException”的异常。经过裁减,增量值为100。s.Length = 1073741100,时间为08/05/2019 12:06,
由于String.Length
是一个整数(它是Int32
的别名),因此它的大小限制为Int32.MaxValue
个Unicode字符。;-)
200兆字节...在这一点上,您的应用程序会变得非常缓慢,占用大约1GB的工作集内存,操作系统开始表现得好像您需要重新启动。
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
字符串在RAM的堆中动态分配内存大小。但是字符串地址存储在占用4个字节内存的栈中。
byte[]
最大大小的相关问题。 - svick